From 271e8ce78c73e1f7a0635442c4f1912335ea497c Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Tue, 1 Nov 2022 13:53:38 +0000 Subject: [PATCH 001/223] Initial commit for SpacetimeDBUnitySDK (squashed commit) --- sdks/csharp/.gitignore | 75 + sdks/csharp/Assets/ExportPackage.cs | 12 + sdks/csharp/Assets/ExportPackage.cs.meta | 11 + sdks/csharp/Assets/Main.unity | 301 + sdks/csharp/Assets/Main.unity.meta | 7 + sdks/csharp/Assets/Materials.meta | 8 + sdks/csharp/Assets/Materials/Skybox_Mat.mat | 89 + .../Assets/Materials/Skybox_Mat.mat.meta | 8 + sdks/csharp/Assets/Presets.meta | 8 + .../Presets/AudioCompressedInMemory.preset | 137 + .../AudioCompressedInMemory.preset.meta | 8 + .../Assets/Presets/AudioStreaming.preset | 137 + .../Assets/Presets/AudioStreaming.preset.meta | 8 + sdks/csharp/Assets/Presets/Defaults.meta | 8 + .../Defaults/AlbedoTexture_Default.preset | 497 + .../AlbedoTexture_Default.preset.meta | 8 + .../Defaults/AudioDecompressOnLoad.preset | 137 + .../AudioDecompressOnLoad.preset.meta | 8 + .../Defaults/DirectionalLight_Default.preset | 137 + .../DirectionalLight_Default.preset.meta | 8 + .../Assets/Presets/NormalTexture.preset | 497 + .../Assets/Presets/NormalTexture.preset.meta | 8 + .../Assets/Presets/UtilityTexture.preset | 497 + .../Assets/Presets/UtilityTexture.preset.meta | 8 + sdks/csharp/Assets/Settings.meta | 8 + .../Assets/Settings/ForwardRenderer.asset | 36 + .../Settings/ForwardRenderer.asset.meta | 8 + .../Assets/Settings/SampleSceneProfile.asset | 118 + .../Settings/SampleSceneProfile.asset.meta | 8 + .../Settings/UniversalRP-HighQuality.asset | 53 + .../UniversalRP-HighQuality.asset.meta | 8 + .../Settings/UniversalRP-LowQuality.asset | 53 + .../UniversalRP-LowQuality.asset.meta | 8 + .../Settings/UniversalRP-MediumQuality.asset | 53 + .../UniversalRP-MediumQuality.asset.meta | 8 + sdks/csharp/Assets/SpacetimeDB.meta | 8 + sdks/csharp/Assets/SpacetimeDB/Packages.meta | 8 + .../Packages/Google.Protobuf.3.21.9.meta | 8 + .../Google.Protobuf.3.21.9.nupkg | Bin 0 -> 1208111 bytes .../Google.Protobuf.3.21.9.nupkg.meta | 7 + .../Packages/Google.Protobuf.3.21.9/lib.meta | 8 + .../Google.Protobuf.3.21.9/lib/net45.meta | 8 + .../lib/net45/Google.Protobuf.dll | Bin 0 -> 410904 bytes .../lib/net45/Google.Protobuf.dll.meta | 33 + .../lib/net45/Google.Protobuf.xml | 10465 ++++++++++++++++ .../lib/net45/Google.Protobuf.xml.meta | 7 + .../Packages/System.Buffers.4.4.0.meta | 8 + .../Packages/System.Buffers.4.4.0/LICENSE.TXT | 23 + .../System.Buffers.4.4.0/LICENSE.TXT.meta | 7 + .../System.Buffers.4.4.0.nupkg | Bin 0 -> 78363 bytes .../System.Buffers.4.4.0.nupkg.meta | 7 + .../THIRD-PARTY-NOTICES.TXT | 226 + .../THIRD-PARTY-NOTICES.TXT.meta | 7 + .../Packages/System.Buffers.4.4.0/lib.meta | 8 + .../lib/netstandard2.0.meta | 8 + .../lib/netstandard2.0/System.Buffers.dll | Bin 0 -> 27992 bytes .../netstandard2.0/System.Buffers.dll.meta | 33 + .../lib/netstandard2.0/System.Buffers.xml | 39 + .../netstandard2.0/System.Buffers.xml.meta | 7 + .../useSharedDesignerContext.txt | 0 .../useSharedDesignerContext.txt.meta | 7 + .../Packages/System.Buffers.4.4.0/version.txt | 1 + .../System.Buffers.4.4.0/version.txt.meta | 7 + .../Packages/System.Memory.4.5.3.meta | 8 + .../Packages/System.Memory.4.5.3/LICENSE.TXT | 23 + .../System.Memory.4.5.3/LICENSE.TXT.meta | 7 + .../System.Memory.4.5.3.nupkg | Bin 0 -> 154054 bytes .../System.Memory.4.5.3.nupkg.meta | 7 + .../THIRD-PARTY-NOTICES.TXT | 309 + .../THIRD-PARTY-NOTICES.TXT.meta | 7 + .../Packages/System.Memory.4.5.3/lib.meta | 8 + .../lib/netstandard2.0.meta | 8 + .../lib/netstandard2.0/System.Memory.dll | Bin 0 -> 148760 bytes .../lib/netstandard2.0/System.Memory.dll.meta | 33 + .../lib/netstandard2.0/System.Memory.xml | 355 + .../lib/netstandard2.0/System.Memory.xml.meta | 7 + .../useSharedDesignerContext.txt | 0 .../useSharedDesignerContext.txt.meta | 7 + .../Packages/System.Memory.4.5.3/version.txt | 1 + .../System.Memory.4.5.3/version.txt.meta | 7 + ...Runtime.CompilerServices.Unsafe.4.5.2.meta | 8 + .../LICENSE.TXT | 23 + .../LICENSE.TXT.meta | 7 + ...untime.CompilerServices.Unsafe.4.5.2.nupkg | Bin 0 -> 104723 bytes ...e.CompilerServices.Unsafe.4.5.2.nupkg.meta | 7 + .../THIRD-PARTY-NOTICES.TXT | 309 + .../THIRD-PARTY-NOTICES.TXT.meta | 7 + .../lib.meta | 8 + .../lib/netstandard2.0.meta | 8 + ...System.Runtime.CompilerServices.Unsafe.dll | Bin 0 -> 23600 bytes ...m.Runtime.CompilerServices.Unsafe.dll.meta | 33 + ...System.Runtime.CompilerServices.Unsafe.xml | 200 + ...m.Runtime.CompilerServices.Unsafe.xml.meta | 7 + .../useSharedDesignerContext.txt | 0 .../useSharedDesignerContext.txt.meta | 7 + .../version.txt | 1 + .../version.txt.meta | 7 + sdks/csharp/Assets/SpacetimeDB/Scripts.meta | 8 + .../Assets/SpacetimeDB/Scripts/ClientApi.cs | 1709 +++ .../SpacetimeDB/Scripts/ClientApi.cs.meta | 11 + .../Assets/SpacetimeDB/Scripts/IStdbTable.cs | 5 + .../SpacetimeDB/Scripts/IStdbTable.cs.meta | 11 + .../SpacetimeDB/Scripts/StdbClientCache.cs | 178 + .../Scripts/StdbClientCache.cs.meta | 3 + .../SpacetimeDB/Scripts/StdbNetworkManager.cs | 367 + .../Scripts/StdbNetworkManager.cs.meta | 11 + .../Assets/SpacetimeDB/Scripts/TypeDef.cs | 496 + .../SpacetimeDB/Scripts/TypeDef.cs.meta | 3 + .../Assets/SpacetimeDB/Scripts/WebSocket.cs | 260 + .../SpacetimeDB/Scripts/WebSocket.cs.meta | 3 + sdks/csharp/Packages/manifest.json | 44 + sdks/csharp/Packages/packages-lock.json | 403 + .../csharp/ProjectSettings/AudioManager.asset | 19 + .../ProjectSettings/ClusterInputManager.asset | 6 + .../ProjectSettings/DynamicsManager.asset | 36 + .../ProjectSettings/EditorBuildSettings.asset | 11 + .../ProjectSettings/EditorSettings.asset | 31 + .../ProjectSettings/GraphicsSettings.asset | 68 + .../csharp/ProjectSettings/InputManager.asset | 487 + .../csharp/ProjectSettings/NavMeshAreas.asset | 91 + .../PackageManagerSettings.asset | 43 + .../ProjectSettings/Physics2DSettings.asset | 56 + .../ProjectSettings/PresetManager.asset | 27 + .../ProjectSettings/ProjectSettings.asset | 698 ++ .../csharp/ProjectSettings/ProjectVersion.txt | 2 + .../ProjectSettings/QualitySettings.asset | 128 + .../SceneTemplateSettings.json | 167 + sdks/csharp/ProjectSettings/TagManager.asset | 43 + sdks/csharp/ProjectSettings/TimeManager.asset | 9 + .../ProjectSettings/URPProjectSettings.asset | 15 + .../UnityConnectSettings.asset | 35 + sdks/csharp/ProjectSettings/VFXManager.asset | 11 + .../VersionControlSettings.asset | 8 + sdks/csharp/ProjectSettings/XRSettings.asset | 10 + sdks/csharp/export.sh | 11 + 135 files changed, 20866 insertions(+) create mode 100644 sdks/csharp/.gitignore create mode 100644 sdks/csharp/Assets/ExportPackage.cs create mode 100644 sdks/csharp/Assets/ExportPackage.cs.meta create mode 100644 sdks/csharp/Assets/Main.unity create mode 100644 sdks/csharp/Assets/Main.unity.meta create mode 100644 sdks/csharp/Assets/Materials.meta create mode 100644 sdks/csharp/Assets/Materials/Skybox_Mat.mat create mode 100644 sdks/csharp/Assets/Materials/Skybox_Mat.mat.meta create mode 100644 sdks/csharp/Assets/Presets.meta create mode 100644 sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset create mode 100644 sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset.meta create mode 100644 sdks/csharp/Assets/Presets/AudioStreaming.preset create mode 100644 sdks/csharp/Assets/Presets/AudioStreaming.preset.meta create mode 100644 sdks/csharp/Assets/Presets/Defaults.meta create mode 100644 sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset create mode 100644 sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset.meta create mode 100644 sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset create mode 100644 sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset.meta create mode 100644 sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset create mode 100644 sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset.meta create mode 100644 sdks/csharp/Assets/Presets/NormalTexture.preset create mode 100644 sdks/csharp/Assets/Presets/NormalTexture.preset.meta create mode 100644 sdks/csharp/Assets/Presets/UtilityTexture.preset create mode 100644 sdks/csharp/Assets/Presets/UtilityTexture.preset.meta create mode 100644 sdks/csharp/Assets/Settings.meta create mode 100644 sdks/csharp/Assets/Settings/ForwardRenderer.asset create mode 100644 sdks/csharp/Assets/Settings/ForwardRenderer.asset.meta create mode 100644 sdks/csharp/Assets/Settings/SampleSceneProfile.asset create mode 100644 sdks/csharp/Assets/Settings/SampleSceneProfile.asset.meta create mode 100644 sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset create mode 100644 sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset.meta create mode 100644 sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset create mode 100644 sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset.meta create mode 100644 sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset create mode 100644 sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/System.Buffers.4.4.0.nupkg create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/System.Buffers.4.4.0.nupkg.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/THIRD-PARTY-NOTICES.TXT create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/THIRD-PARTY-NOTICES.TXT.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt create mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs.meta create mode 100644 sdks/csharp/Packages/manifest.json create mode 100644 sdks/csharp/Packages/packages-lock.json create mode 100644 sdks/csharp/ProjectSettings/AudioManager.asset create mode 100644 sdks/csharp/ProjectSettings/ClusterInputManager.asset create mode 100644 sdks/csharp/ProjectSettings/DynamicsManager.asset create mode 100644 sdks/csharp/ProjectSettings/EditorBuildSettings.asset create mode 100644 sdks/csharp/ProjectSettings/EditorSettings.asset create mode 100644 sdks/csharp/ProjectSettings/GraphicsSettings.asset create mode 100644 sdks/csharp/ProjectSettings/InputManager.asset create mode 100644 sdks/csharp/ProjectSettings/NavMeshAreas.asset create mode 100644 sdks/csharp/ProjectSettings/PackageManagerSettings.asset create mode 100644 sdks/csharp/ProjectSettings/Physics2DSettings.asset create mode 100644 sdks/csharp/ProjectSettings/PresetManager.asset create mode 100644 sdks/csharp/ProjectSettings/ProjectSettings.asset create mode 100644 sdks/csharp/ProjectSettings/ProjectVersion.txt create mode 100644 sdks/csharp/ProjectSettings/QualitySettings.asset create mode 100644 sdks/csharp/ProjectSettings/SceneTemplateSettings.json create mode 100644 sdks/csharp/ProjectSettings/TagManager.asset create mode 100644 sdks/csharp/ProjectSettings/TimeManager.asset create mode 100644 sdks/csharp/ProjectSettings/URPProjectSettings.asset create mode 100644 sdks/csharp/ProjectSettings/UnityConnectSettings.asset create mode 100644 sdks/csharp/ProjectSettings/VFXManager.asset create mode 100644 sdks/csharp/ProjectSettings/VersionControlSettings.asset create mode 100644 sdks/csharp/ProjectSettings/XRSettings.asset create mode 100644 sdks/csharp/export.sh diff --git a/sdks/csharp/.gitignore b/sdks/csharp/.gitignore new file mode 100644 index 00000000000..116e0d0723c --- /dev/null +++ b/sdks/csharp/.gitignore @@ -0,0 +1,75 @@ +# This .gitignore file should be placed at the root of your Unity project directory +# +# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore +# +/[Ll]ibrary/ +/[Tt]emp/ +/[Oo]bj/ +/[Bb]uild/ +/[Bb]uilds/ +/[Ll]ogs/ +/[Uu]ser[Ss]ettings/ + +# MemoryCaptures can get excessive in size. +# They also could contain extremely sensitive data +/[Mm]emoryCaptures/ + +# Recordings can get excessive in size +/[Rr]ecordings/ + +# Uncomment this line if you wish to ignore the asset store tools plugin +# /[Aa]ssets/AssetStoreTools* + +# Autogenerated Jetbrains Rider plugin +/[Aa]ssets/Plugins/Editor/JetBrains* + +# Visual Studio cache directory +.vs/ + +# Gradle cache directory +.gradle/ + +# Autogenerated VS/MD/Consulo solution and project files +ExportedObj/ +.consulo/ +*.csproj +*.unityproj +*.sln +*.suo +*.tmp +*.user +*.userprefs +*.pidb +*.booproj +*.svd +*.pdb +*.mdb +*.opendb +*.VC.db + +# Unity3D generated meta files +*.pidb.meta +*.pdb.meta +*.mdb.meta + +# Unity3D generated file on crash reports +sysinfo.txt + +# Builds +*.apk +*.aab +*.unitypackage +*.app + +# Crashlytics generated file +crashlytics-build.properties + +# Packed Addressables +/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* + +# Temporary auto-generated Android Assets +/[Aa]ssets/[Ss]treamingAssets/aa.meta +/[Aa]ssets/[Ss]treamingAssets/aa/* + +.idea +*.unitypackage diff --git a/sdks/csharp/Assets/ExportPackage.cs b/sdks/csharp/Assets/ExportPackage.cs new file mode 100644 index 00000000000..70e15566919 --- /dev/null +++ b/sdks/csharp/Assets/ExportPackage.cs @@ -0,0 +1,12 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +public class ExportPackage +{ + public static void Export() + { + AssetDatabase.ExportPackage("Assets/SpacetimeDB", "SpacetimeDBUnitySDK.unitypackage", ExportPackageOptions.Recurse); + } +} diff --git a/sdks/csharp/Assets/ExportPackage.cs.meta b/sdks/csharp/Assets/ExportPackage.cs.meta new file mode 100644 index 00000000000..d56b6fc11df --- /dev/null +++ b/sdks/csharp/Assets/ExportPackage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 54770d36c73a74a6db05cfc84d75f761 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Main.unity b/sdks/csharp/Assets/Main.unity new file mode 100644 index 00000000000..7582fbead7b --- /dev/null +++ b/sdks/csharp/Assets/Main.unity @@ -0,0 +1,301 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.18028328, g: 0.22571328, b: 0.3069218, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &870692381 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 870692384} + - component: {fileID: 870692383} + - component: {fileID: 870692382} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &870692382 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 870692381} + m_Enabled: 1 +--- !u!20 &870692383 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 870692381} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &870692384 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 870692381} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1777449238 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1777449240} + - component: {fileID: 1777449239} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1777449239 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1777449238} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.02 + m_NormalBias: 0.1 + m_NearPlane: 0.1 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1777449240 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1777449238} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} diff --git a/sdks/csharp/Assets/Main.unity.meta b/sdks/csharp/Assets/Main.unity.meta new file mode 100644 index 00000000000..56f79e86662 --- /dev/null +++ b/sdks/csharp/Assets/Main.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b7991f809bde6e4419a94e030a8bcb16 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Materials.meta b/sdks/csharp/Assets/Materials.meta new file mode 100644 index 00000000000..ee17c23bb89 --- /dev/null +++ b/sdks/csharp/Assets/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0234ba368eeec9418390da711bfdad0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Materials/Skybox_Mat.mat b/sdks/csharp/Assets/Materials/Skybox_Mat.mat new file mode 100644 index 00000000000..ba73d5da58f --- /dev/null +++ b/sdks/csharp/Assets/Materials/Skybox_Mat.mat @@ -0,0 +1,89 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Skybox_Mat + m_Shader: {fileID: 106, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _METALLIC_SETUP _SUNDISK_HIGH_QUALITY + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _AtmosphereThickness: 0.53 + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _Exposure: 1.25 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SunDisk: 2 + - _SunSize: 0.04 + - _SunSizeConvergence: 5 + - _UVSec: 0 + - _WorkflowMode: 1 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _GroundColor: {r: 0.6392157, g: 0.6901961, b: 0.7411765, a: 1} + - _SkyTint: {r: 1, g: 1, b: 1, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} diff --git a/sdks/csharp/Assets/Materials/Skybox_Mat.mat.meta b/sdks/csharp/Assets/Materials/Skybox_Mat.mat.meta new file mode 100644 index 00000000000..facef4afefe --- /dev/null +++ b/sdks/csharp/Assets/Materials/Skybox_Mat.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0ffaa0b7117ba8c47a9d05ae701d4b4d +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets.meta b/sdks/csharp/Assets/Presets.meta new file mode 100644 index 00000000000..c3a6623f4d5 --- /dev/null +++ b/sdks/csharp/Assets/Presets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 558255460b74ec04fa70b5570e9327bd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset b/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset new file mode 100644 index 00000000000..4ca91acf3df --- /dev/null +++ b/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: AudioCompressedInMemory + m_TargetType: + m_NativeTypeID: 1020 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_ExternalObjects.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.loadType + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.compressionFormat + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.quality + value: 0.7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.size + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].first + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.loadType + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.compressionFormat + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.quality + value: 0.7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].first + value: 7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.loadType + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.compressionFormat + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.quality + value: 0.7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ForceToMono + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Normalize + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PreloadAudioData + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LoadInBackground + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Ambisonic + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_3D + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_UserData + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleName + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleVariant + value: + objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset.meta b/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset.meta new file mode 100644 index 00000000000..cd0d5633dc2 --- /dev/null +++ b/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2dd802e4d37c65149922028d3e973832 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/AudioStreaming.preset b/sdks/csharp/Assets/Presets/AudioStreaming.preset new file mode 100644 index 00000000000..8499ed8c629 --- /dev/null +++ b/sdks/csharp/Assets/Presets/AudioStreaming.preset @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: AudioStreaming + m_TargetType: + m_NativeTypeID: 1020 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_ExternalObjects.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.loadType + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.compressionFormat + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.quality + value: 0.7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.size + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].first + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.loadType + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.compressionFormat + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.quality + value: 0.7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].first + value: 7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.loadType + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.compressionFormat + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.quality + value: 0.7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ForceToMono + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Normalize + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PreloadAudioData + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LoadInBackground + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Ambisonic + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_3D + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_UserData + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleName + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleVariant + value: + objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/AudioStreaming.preset.meta b/sdks/csharp/Assets/Presets/AudioStreaming.preset.meta new file mode 100644 index 00000000000..b7b81180255 --- /dev/null +++ b/sdks/csharp/Assets/Presets/AudioStreaming.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 86bcce7f5575b54408aa0f3a7d321039 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/Defaults.meta b/sdks/csharp/Assets/Presets/Defaults.meta new file mode 100644 index 00000000000..959a49bd8da --- /dev/null +++ b/sdks/csharp/Assets/Presets/Defaults.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 71ea82b02df99c2439e0dc8e4e1ebc24 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset b/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset new file mode 100644 index 00000000000..6137100f126 --- /dev/null +++ b/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset @@ -0,0 +1,497 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: AlbedoTexture_Default + m_TargetType: + m_NativeTypeID: 1006 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_FileIDToRecycleName.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ExternalObjects.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EnableMipMap + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_sRGBTexture + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LinearTexture + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_FadeOut + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_BorderMipMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapsPreserveCoverage + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaTestReferenceValue + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapFadeDistanceStart + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapFadeDistanceEnd + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ConvertToNormalMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ExternalNormalMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_HeightScale + value: 0.25 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_NormalMapFilter + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_IsReadable + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_StreamingMipmaps + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_StreamingMipmapsPriority + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_GrayScaleToAlpha + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_GenerateCubemap + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CubemapConvolution + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SeamlessCubemap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureFormat + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MaxTextureSize + value: 2048 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_FilterMode + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_Aniso + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_MipBias + value: -100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapU + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapV + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapW + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_NPOTScale + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Lightmap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteExtrude + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteMeshType + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Alignment + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePixelsToUnits + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.w + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteGenerateFallbackPhysicsShape + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaUsage + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaIsTransparency + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteTessellationDetail + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureType + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureShape + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SingleChannelComponent + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MaxTextureSizeSet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CompressionQualitySet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureFormatSet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.size + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget + value: DefaultTexturePlatform + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget + value: Standalone + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_BuildTarget + value: iPhone + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_BuildTarget + value: Android + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_BuildTarget + value: Windows Store Apps + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Sprites.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Outline.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Bones.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_SpriteID + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Vertices.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Indices.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Edges.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Weights.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePackingTag + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PSDRemoveMatte + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PSDShowRemoveMatteOption + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_UserData + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleName + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleVariant + value: + objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset.meta b/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset.meta new file mode 100644 index 00000000000..2e7fd878e49 --- /dev/null +++ b/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e8537455c6c08bd4e8bf0be3707da685 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset b/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset new file mode 100644 index 00000000000..dd415f614c9 --- /dev/null +++ b/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: AudioDecompressOnLoad + m_TargetType: + m_NativeTypeID: 1020 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_ExternalObjects.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.loadType + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.compressionFormat + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.quality + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DefaultSettings.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.size + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].first + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.loadType + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.compressionFormat + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.quality + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[0].second.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].first + value: 7 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.loadType + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateSetting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateOverride + value: 44100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.compressionFormat + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.quality + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettingOverrides.Array.data[1].second.conversionMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ForceToMono + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Normalize + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PreloadAudioData + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LoadInBackground + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Ambisonic + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_3D + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_UserData + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleName + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleVariant + value: + objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset.meta b/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset.meta new file mode 100644 index 00000000000..8e3dd0256da --- /dev/null +++ b/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e7689051185d12f4298e1ebb2693a29f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset b/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset new file mode 100644 index 00000000000..24034e46df9 --- /dev/null +++ b/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: DirectionalLight_Default + m_TargetType: + m_NativeTypeID: 108 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Type + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Color.r + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Color.g + value: 0.95686275 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Color.b + value: 0.8392157 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Color.a + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Intensity + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Range + value: 10 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpotAngle + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CookieSize + value: 10 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Shadows.m_Type + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Shadows.m_Resolution + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Shadows.m_CustomResolution + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Shadows.m_Strength + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Shadows.m_Bias + value: 0.02 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Shadows.m_NormalBias + value: 0.1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Shadows.m_NearPlane + value: 0.1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Cookie + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_DrawHalo + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Flare + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_RenderMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CullingMask.m_Bits + value: 4294967295 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Lightmapping + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LightShadowCasterMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AreaSize.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AreaSize.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_BounceIntensity + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ColorTemperature + value: 6570 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_UseColorTemperature + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ShadowRadius + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ShadowAngle + value: 0 + objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset.meta b/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset.meta new file mode 100644 index 00000000000..ac83bf91c7c --- /dev/null +++ b/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 463065d4f17d1d94d848aa127b94dd43 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/NormalTexture.preset b/sdks/csharp/Assets/Presets/NormalTexture.preset new file mode 100644 index 00000000000..c6a771f40e8 --- /dev/null +++ b/sdks/csharp/Assets/Presets/NormalTexture.preset @@ -0,0 +1,497 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: NormalTexture + m_TargetType: + m_NativeTypeID: 1006 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_FileIDToRecycleName.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ExternalObjects.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EnableMipMap + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_sRGBTexture + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LinearTexture + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_FadeOut + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_BorderMipMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapsPreserveCoverage + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaTestReferenceValue + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapFadeDistanceStart + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapFadeDistanceEnd + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ConvertToNormalMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ExternalNormalMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_HeightScale + value: 0.25 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_NormalMapFilter + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_IsReadable + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_StreamingMipmaps + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_StreamingMipmapsPriority + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_GrayScaleToAlpha + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_GenerateCubemap + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CubemapConvolution + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SeamlessCubemap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureFormat + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MaxTextureSize + value: 2048 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_FilterMode + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_Aniso + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_MipBias + value: -100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapU + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapV + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapW + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_NPOTScale + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Lightmap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteExtrude + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteMeshType + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Alignment + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePixelsToUnits + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.w + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteGenerateFallbackPhysicsShape + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaUsage + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaIsTransparency + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteTessellationDetail + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureType + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureShape + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SingleChannelComponent + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MaxTextureSizeSet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CompressionQualitySet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureFormatSet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.size + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget + value: DefaultTexturePlatform + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget + value: Standalone + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_BuildTarget + value: iPhone + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_BuildTarget + value: Android + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_BuildTarget + value: Windows Store Apps + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Sprites.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Outline.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Bones.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_SpriteID + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Vertices.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Indices.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Edges.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Weights.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePackingTag + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PSDRemoveMatte + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PSDShowRemoveMatteOption + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_UserData + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleName + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleVariant + value: + objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/NormalTexture.preset.meta b/sdks/csharp/Assets/Presets/NormalTexture.preset.meta new file mode 100644 index 00000000000..33fcecf55be --- /dev/null +++ b/sdks/csharp/Assets/Presets/NormalTexture.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 14a57cf3b9fa1c74b884aa7e0dcf1faa +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/UtilityTexture.preset b/sdks/csharp/Assets/Presets/UtilityTexture.preset new file mode 100644 index 00000000000..6b879d82c31 --- /dev/null +++ b/sdks/csharp/Assets/Presets/UtilityTexture.preset @@ -0,0 +1,497 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: UtilityTexture + m_TargetType: + m_NativeTypeID: 1006 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_FileIDToRecycleName.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ExternalObjects.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EnableMipMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_sRGBTexture + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LinearTexture + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_FadeOut + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_BorderMipMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapsPreserveCoverage + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaTestReferenceValue + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapFadeDistanceStart + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MipMapFadeDistanceEnd + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ConvertToNormalMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ExternalNormalMap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_HeightScale + value: 0.25 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_NormalMapFilter + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_IsReadable + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_StreamingMipmaps + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_StreamingMipmapsPriority + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_GrayScaleToAlpha + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_GenerateCubemap + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CubemapConvolution + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SeamlessCubemap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureFormat + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MaxTextureSize + value: 2048 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_FilterMode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_Aniso + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_MipBias + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapU + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapV + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureSettings.m_WrapW + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_NPOTScale + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Lightmap + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteMode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteExtrude + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteMeshType + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_Alignment + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePixelsToUnits + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteBorder.w + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteGenerateFallbackPhysicsShape + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaUsage + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AlphaIsTransparency + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteTessellationDetail + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureType + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureShape + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SingleChannelComponent + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_MaxTextureSizeSet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CompressionQualitySet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_TextureFormatSet + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.size + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget + value: DefaultTexturePlatform + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget + value: Standalone + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_BuildTarget + value: iPhone + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[2].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_BuildTarget + value: Android + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_TextureCompression + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[3].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_BuildTarget + value: Windows Store Apps + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_MaxTextureSize + value: 8192 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_ResizeAlgorithm + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_TextureFormat + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_TextureCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_CompressionQuality + value: 50 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_CrunchedCompression + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_AllowsAlphaSplitting + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_Overridden + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PlatformSettings.Array.data[4].m_AndroidETC2FallbackOverride + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Sprites.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Outline.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Bones.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_SpriteID + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Vertices.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Indices.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Edges.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpriteSheet.m_Weights.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_SpritePackingTag + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PSDRemoveMatte + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_PSDShowRemoveMatteOption + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_UserData + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleName + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AssetBundleVariant + value: + objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/UtilityTexture.preset.meta b/sdks/csharp/Assets/Presets/UtilityTexture.preset.meta new file mode 100644 index 00000000000..a11d2e93d1b --- /dev/null +++ b/sdks/csharp/Assets/Presets/UtilityTexture.preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 45f7b2e3c78185248b3adbb14429c2ab +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings.meta b/sdks/csharp/Assets/Settings.meta new file mode 100644 index 00000000000..8e9f13c8f03 --- /dev/null +++ b/sdks/csharp/Assets/Settings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0735c275001a2c84dafdb30deced5d8d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/ForwardRenderer.asset b/sdks/csharp/Assets/Settings/ForwardRenderer.asset new file mode 100644 index 00000000000..4514a2b8a1a --- /dev/null +++ b/sdks/csharp/Assets/Settings/ForwardRenderer.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: ForwardRenderer + m_EditorClassIdentifier: + m_RendererFeatures: [] + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + shaders: + blitPS: {fileID: 4800000, guid: c17132b1f77d20942aa75f8429c0f8bc, type: 3} + copyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + screenSpaceShadowPS: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, + type: 3} + samplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + fallbackErrorPS: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 0 + failOperation: 0 + zFailOperation: 0 diff --git a/sdks/csharp/Assets/Settings/ForwardRenderer.asset.meta b/sdks/csharp/Assets/Settings/ForwardRenderer.asset.meta new file mode 100644 index 00000000000..06d9cabc24e --- /dev/null +++ b/sdks/csharp/Assets/Settings/ForwardRenderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a8e21d5c33334b11b34a596161b9360 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/SampleSceneProfile.asset b/sdks/csharp/Assets/Settings/SampleSceneProfile.asset new file mode 100644 index 00000000000..cbc629b5cd2 --- /dev/null +++ b/sdks/csharp/Assets/Settings/SampleSceneProfile.asset @@ -0,0 +1,118 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-7893295128165547882 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0b2db86121404754db890f4c8dfe81b2, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + m_AdvancedMode: 0 + threshold: + m_OverrideState: 1 + m_Value: 1 + min: 0 + intensity: + m_OverrideState: 1 + m_Value: 1 + min: 0 + scatter: + m_OverrideState: 0 + m_Value: 0.7 + min: 0 + max: 1 + clamp: + m_OverrideState: 0 + m_Value: 65472 + min: 0 + tint: + m_OverrideState: 0 + m_Value: {r: 1, g: 1, b: 1, a: 1} + hdr: 0 + showAlpha: 0 + showEyeDropper: 1 + highQualityFiltering: + m_OverrideState: 0 + m_Value: 0 + dirtTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + dirtIntensity: + m_OverrideState: 0 + m_Value: 0 + min: 0 +--- !u!114 &-7011558710299706105 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 899c54efeace73346a0a16faa3afe726, type: 3} + m_Name: Vignette + m_EditorClassIdentifier: + active: 1 + m_AdvancedMode: 0 + color: + m_OverrideState: 0 + m_Value: {r: 0, g: 0, b: 0, a: 1} + hdr: 0 + showAlpha: 0 + showEyeDropper: 1 + center: + m_OverrideState: 0 + m_Value: {x: 0.5, y: 0.5} + intensity: + m_OverrideState: 1 + m_Value: 0.25 + min: 0 + max: 1 + smoothness: + m_OverrideState: 1 + m_Value: 0.4 + min: 0.01 + max: 1 + rounded: + m_OverrideState: 0 + m_Value: 0 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: SampleSceneProfile + m_EditorClassIdentifier: + components: + - {fileID: 849379129802519247} + - {fileID: -7893295128165547882} + - {fileID: -7011558710299706105} +--- !u!114 &849379129802519247 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 97c23e3b12dc18c42a140437e53d3951, type: 3} + m_Name: Tonemapping + m_EditorClassIdentifier: + active: 1 + m_AdvancedMode: 0 + mode: + m_OverrideState: 1 + m_Value: 2 diff --git a/sdks/csharp/Assets/Settings/SampleSceneProfile.asset.meta b/sdks/csharp/Assets/Settings/SampleSceneProfile.asset.meta new file mode 100644 index 00000000000..b82270c5b28 --- /dev/null +++ b/sdks/csharp/Assets/Settings/SampleSceneProfile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10fc4df2da32a41aaa32d77bc913491c +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset b/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset new file mode 100644 index 00000000000..2ac23c8bcd5 --- /dev/null +++ b/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset @@ -0,0 +1,53 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: UniversalRP-HighQuality + m_EditorClassIdentifier: + k_AssetVersion: 5 + k_AssetPreviousVersion: 5 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: 4a8e21d5c33334b11b34a596161b9360, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsHDR: 1 + m_MSAA: 2 + m_RenderScale: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 2048 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 1 + m_AdditionalLightsShadowmapResolution: 512 + m_ShadowDistance: 50 + m_ShadowCascades: 1 + m_Cascade2Split: 0.25 + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_SoftShadowsSupported: 1 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_DebugLevel: 0 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_ShaderVariantLogLevel: 0 diff --git a/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset.meta b/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset.meta new file mode 100644 index 00000000000..c8fa31758a9 --- /dev/null +++ b/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 19ba41d7c0026c3459d37c2fe90c55a0 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset b/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset new file mode 100644 index 00000000000..ab81d03f0fb --- /dev/null +++ b/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset @@ -0,0 +1,53 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: UniversalRP-LowQuality + m_EditorClassIdentifier: + k_AssetVersion: 5 + k_AssetPreviousVersion: 5 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: 4a8e21d5c33334b11b34a596161b9360, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsHDR: 0 + m_MSAA: 1 + m_RenderScale: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 0 + m_MainLightShadowmapResolution: 2048 + m_AdditionalLightsRenderingMode: 0 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 512 + m_ShadowDistance: 50 + m_ShadowCascades: 0 + m_Cascade2Split: 0.25 + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_SoftShadowsSupported: 0 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_DebugLevel: 0 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 16 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_ShaderVariantLogLevel: 0 diff --git a/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset.meta b/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset.meta new file mode 100644 index 00000000000..040da39e5b0 --- /dev/null +++ b/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a31e9f9f9c9d4b9429ed0d1234e22103 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset b/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset new file mode 100644 index 00000000000..23de11bf084 --- /dev/null +++ b/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset @@ -0,0 +1,53 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: UniversalRP-MediumQuality + m_EditorClassIdentifier: + k_AssetVersion: 5 + k_AssetPreviousVersion: 5 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: 4a8e21d5c33334b11b34a596161b9360, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsHDR: 0 + m_MSAA: 1 + m_RenderScale: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 2048 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 512 + m_ShadowDistance: 50 + m_ShadowCascades: 0 + m_Cascade2Split: 0.25 + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_SoftShadowsSupported: 0 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_DebugLevel: 0 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_ShaderVariantLogLevel: 0 diff --git a/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset.meta b/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset.meta new file mode 100644 index 00000000000..d8477b75449 --- /dev/null +++ b/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d847b876476d3d6468f5dfcd34266f96 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB.meta b/sdks/csharp/Assets/SpacetimeDB.meta new file mode 100644 index 00000000000..5dc6b0124a4 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8c3f00f56e2ad68e986763d9f99b3e1d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages.meta b/sdks/csharp/Assets/SpacetimeDB/Packages.meta new file mode 100644 index 00000000000..223280800ba --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 086bf95e1033970ad9bf698d2215ebac +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9.meta new file mode 100644 index 00000000000..72c8721ddb7 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 345dd82d825150bb68d5624d1e1392ce +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..1758cdd1b7e962d7c75317d3a9038328d8a3efca GIT binary patch literal 1208111 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
fX`3 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 PkBqR-?P+CubS8py(RN01~ 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�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�qMI{h55)M^ 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
R(Ow2H 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

HPG(j2*)3}gs2{Q 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 z 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 z zoERiG*V{7Y=&9S)a~he>%#x0*gte?;MYA6+*`_YY;QoLQ;9jb*EWW%p!p8Hg-?;Lv zgHDec&?dWQC2vdCyNaNToa$#P0nbz9k!8dmXKMz7_sC z?YRp#hnh8?|7@>Dz<=m_Kle_|ex2sKywyHmdTJhf)}(cQ`si_M4m?o2$XS}y=-XtY z6DxZ3B$gD3Gx^CKYGt$hne&(z?71O#cN)w)zWa0YNY&D-1-$$3bCuS7j{@hKGx(1h zY!2l9`{+)u!!{0+?;oulv*`P^J!f0{)F&JsYV_SMRr;*q$23)uCy_LR&7--A<}zC~ z-n+&{sa~&rUA-es^Jm5MyAwAh{z%-Jcjq&sP)BrHAifI3nH=Ee?cVfg-0{ABuP(1K zT5^AAt6e|8J?U-1i#2OIqLZU0d1)l(RSYT2`NJ5d%W@n0jQVuWK~wp3x~H|f{+Goa zX^y%lGq!x4ws?N@%t*$3twi#mPf`XEi!kon2kGDUw{CSGecAU?Qp4wkEklPb=yCVC zyTQ#;x|NT>9|l6Dv!1OwF1!b;io;H&RTTT;_fFr1Q_L=U=|= zZPrO7hr6H!LF^rtS5zh**-bynojXtU^R{b+HK+GayVCMy`=<2EYiAv7pOo-8HT2N# z{_8I(CzlK^DXl3XLl7Zn$a70Prl0tD%l`eMISFBfTQ14Y4{ED%{-a^UPJ9m;G#yZ_H$XZ{rwCigF!3oRclIx;JIxBXhKom^6xl}}FT zV?pFBi9loqpX>5T-`y~s1-rsKjI(I{VZ=WAZsd+_3kthH; zfMNNUh-q)e!5J60mBvq}+(;Sh)0}^!`N2u+A>*F;Y+2E^dW-5`qXX66rL5op1kbe# zvx>x#GiA8T5>l2uX1gjSx>T+*+r0gb*Pf{rtPL}pD}&u0Dd#B0u>8vke}njPPsSCV z->j&i{o~n%;dl0%z4;iEl5t1=wba}t*Od*ZWNU?>YROOoa1~t5zDE+&cO5RBE^xYv=xGR1@O5lXMODuaEtYENr&=ds1rK?(KfBmmVIL_2^qh z>rz|$<@atjOkczfE-oXGSQ;ntyK^w5)N;=svr( z3!=sfTy+v;ysw9#}CZc3P1fI>kY%{f| z{p|TUVUDK)Y(3p`j(<4Cp4q4OkZrli2bVQA4wOqIPv?I_UE-EK_*OjcaYx#!_5Z$| za?#!Tq3kWFQ_|swN&_sj_sLGyEle7wOhUEp`uo8BwZP|V$+((P z8Ut$&)_%J>@r-fx;QYOaDPXA$A%IC1wxs5_qsy-|=n>hauguamP9 zfBsy)e%Z$IYo5Qh?o>`UQWN4t-HPCa+*Xd;p@u{+MnCSV&_#Y7F@-_1<+ZG8CQN;2 zVLs&9@CHt5VMQJ}77#Npb5?QPHYGfJ^(i8Y_t1LR#qlH3Qf*wEr+&%#e9P;{lbpXi zZfW4dY$Ii5^3k*bX$(&Wh<~lch$oagMOU3W*6oo&YXS#l`|Hi*oM>iyo z()4xtHs$G|8tKyPL9z*XMR^bm%ar6*xjEX~#{?$@mR98XmzCM3R<1QQ$F3;w@cr-L0%2szb@1WHS7Y|fO{}e~$}9Hzy=pItA>d9%7A;C|Zb4CLc2-gE z-a@kKk}BA6_O#%@z&?pQQ0+W=?3CWh^iLx-wdHn_2NhQ0 z;>AtB)m$^9Z07gij!o-ymG(?;SJJeh zSHY(++k!(eOO|J(rzhJc>ijEU>t>^+HT#Dhu#HM~x!q4aeQxc6=}*qgF`cvbQXd~? zh(h}30RvXO;(0F$c&v0Gu~&*#kC(in!H$Np`77UK%KI*TkaET0ys!Z(hA*9N2(d9kuW1|g*^?p~(wu6H?J7-s4>xtlbm(c?+jL-6Ras?k2ZxHR8vBC6s)5zn)s=Y_ zIcTR!z)qDGJCxC9vDw7*RSN1*ame*_&&_ts^UU?g%lFLl%<1LknwRI4pP!ZE=Hc$< z>gn#8?~?8A?hO5m99f?@M6m8DXYyJJq?r|V!X{VP^Nx1z_Rdaj&iHAQ(<|3K-!nfe z+r!l@KR?&g)y3J#JvYnM-ObV2xtFVJUawpiw|r-3swk_Zpc-ru6=+7k9ATFatnG5h zdj?L9z33MM>;@N>G}L`77Ez(`TB8>{d|JPLxk zz_MzpLa^gIrFJJ$S5y@fxt;Bu9Bo`ZoSpMra$K^qdiBc7_HfR2&d+vn$?*j7^F5ti za`K&=a&vR@+=X(BnDw%Erm9H*OC?p1m)Y_QOW-=eKQP!fG&VLgDmXJPAvP&CAUPy6 zF*z!n5HDTS5rbQ(@(3UlnyGSk4|(Sr|A zTq$bsZcD#yV$r8=fcA`vLGBR1pz2aiG z&3>{VJ>=qCaH0_I!9$*kT$*y`+R?|Tzon>~y;c|98&w;<^Y86zb=MT}X_p1whYmn! zdd>8Q8&H6Y$J+K39&QVt{CW|~rsJCEOfJyu z8ci(rx&d65&@b4~*rCc6AE-t6Pk6U9-M^&}IkRe?^t9fQE4pH7z~RcR=c&6C^>JKr z#ot#MLCZ7KycfG}wCx5EUR+#F-jt=G_jATS#%~=?Gn4&zY_nSU=EsbR_4`)r?FJfC zT0%~&I;ZmP7srz*=ktvo{1+*j0V_MKm7HAjdv=3O#J8Q{v~*aWQ2WJggRdj_;@tf^ zU%h!6HG^qww`1^(%1&@`S!oIAB)T*=ugKoNq@=VeOMJ|7TV^)l%k$p`@A`E$<6P_p z;~}s5d9^(59v_rdmDQEUj=Qg$agt6ow9c|PGBtQc-M2MmNzD3gdC-_8{hvHU%s&iv z?Q{Rrq1!A52k-B&=+iwWcnDnLiDoW&w}$4iUrF%|@_3h$^8AHebnqV575@cVQX-{` z^XR%0w$6Igf~s53b8O%He2af;T1nFYLOIGo9WR$ zMSEWG!hcSeubq3sw39SRT4Io@`GCKfXx2@h@WA?5KQ3a95x6j z$-Lo!iaX_)(s6DZ#bZ#Xr2f9xJE=W-vR#DxI+^xVF#!310})YHNn@MOpE!YI*jeon zyr<`wn7tb=FEjgRnX?#{rqtRy=QWCTS9O%-)@v&Rx4c>H8ZveBCz?|9teR}!s*0?f zDq$xEr%u*mCnvsc^wz3i#LjL~d|sY7-MSlSP+oR*0Sy~)?_WHG-LXI3s6VwmWX@=> z`?Dtb%<2jgyC&(nP?a|)KmLd^?=bmW_j>EPph?+hd;0C3uFwq!Jh!GJYmAL)2DuUI z@1O{q-WR?$*ija>^y%Y_%b}@ryI}w!HXgRoKxQAg^|%+E86__gUtJ1nb<=Ed8@T># zH^4-EyEdsJt5fO~yU$%hsn7qlwDu))LG*mz-pP*kf4Oyo#rG2h=^bGZRR|O%oom{+ zeEl4hzR!m_bB2x43z!oVZ}cXMb*wu^rKLqe*@u3Jx{fgKkvHBA9CjhLg}+PVc4*Cn zZeXO>-&7t`^Y4i$eB8_J&yJ`%hEIwpUyxw2;>91pnD)?CWY?BO2t2Jkp{}n-ZSbVL zg$_4^%I*k&G*S76%(qa$o|9HszsxCm6)%HvyPF(us zEYDS&{~fsfOp$W$q?!*jNN`|K3Heuv6OA}H#`+izcy;Coxr`Xu&}r3fA@6pL@}d!; zBweIqN_%+MIS)K_r!%#irg|E?o5}k3``2$=Bb&x4e)o16w!4NE9Z0MKRD%cKN}V< z_UsinGkN!M!s zfVU3O+u4Ekeg}?6HLCcZ)9!uvp(L8rQnRXZ26mc}lF4F^Y;MZTm_S^-H3joa&X?Qb0I;_&KT=URG4FPtM?-$Px)QiO{p-{!#Yz2xOW z_npFaw4LK)kMb=~^n%Bp4_!Xs^_!v{dv}VEafM}_)MF;xC$4qoG`X1AsoP`zCA-a6 zNooEb5p{A&aaIWkmK!bh^${Aq;r_3g*q6>F<9jK~%VQRqKKWXruv>vfL!MVoQ$9@X zaR%)|Wxt#MT&nyP*xd2;9{0ZE4lzpDH)K_bZ5-`$Y1c8FoE^RxE10Gvnf9RDxp1 zAe(>wZ5i6!XL)gJqB9-v(wY_;##^qpFgW%-d0%CUIm5r@*~qntRC_5+86E=S6 zJ05j2v?hOoRitgemP__$rfX~-C`K3t`9DqV-u}-H%rk19w|?RlJPDooVn=nc@297d z)De}P+uSR2+B_0Mm262V`cW9Ypoex&oa31_5)cW$maZ939Hjb~Ea_htSNe^syfrlY z=2ZhRRCHEhk&ycMo0q7~IqFNlPG0vmV#fIW#-DWa8pWvb%q$@f7IC$hy=*hywT}4y zHhxE+UV}ro?_6rCm27@|dD($Qg`#{=YUS*+xB|i(9?95w zjt<>1_~W$UhU0hs4hbV)aS|n6G&ta}@e~wrwe+4x+H?N)-*bJOQ{;4wUcZAOo*ODu z#LYVzV-WGRwLITbS0;Aijdj8L=_?2Sju4LOH%U{E-2aGBe)Q7F*qD7lthO zv0>s4)e;9u>J(5yX=ea2b=====T`+=)UPsC-XFK3FQ z#pfuqZPF>EFRb#-eAi<`L~HxmySKN$Khu>y81@AXT6k)~XIw~5%g+W!$-Ir;9x}-I z&YY*Ne*lF?k>p)`-;V#nBnKLX|2lGJ?4cp1SsI`lulbbD7H`gy$FCKN`i-Lx&`!@Q8SylsaUth+X~E5C}ul1h<1EPWVuf%=<4 zg~whTcEWsnWc{18ZR=ZXY$R||rD99c_(d!6^}WoDC;pmI8L)9!{M6?Yt~g3yBrNaS zi$_M|?y)Xs$W6Rc9=c$KT&m)mVeceRiGYzz#s+=9z7jiZ`)at(anSLob=wO0Lw9>m z`>#;?WpvSzYT)HNM^FF*8Rr}PCu{whq<$?)ajk#+-?)f}UrIZSNEW$8W96qw@0Ei8 z^&;%}+I>gE{~Nxm5t(pUZxM27x_*n@u9@aPZbxa&vgc0%{wtTX;vyP8+bj12I+oR* zV;k**EbR06=k$9BQmNYi@~=Vnf+uiiP3E(n4e0`^ zs4c51EvU#U8(3@aUsO;Etphu`q?hb?fevH&m4e&NMg`%#UhC#JF_ymkFI=EfSw_QM zwuNsd2Q}4itEyvqgtR<(&U4>Y;KoS-=3_2vJ{CC$yzGZ0_j&M$=Tw|DZ&V0o-T zrK~jaRCk?S7&G_ZCOa{g0U5ivOIf{pxnc!j)|CjGa?ersvf00*em})~Fj$uC5AG(b z4O;$KJh4or^~ z14}N3gR%xB?>!^s;xVykPSBb+CrYLy1Z?XL($(ZQp8E0@(Hjkpc~-Yy@!NNB;?jhM zBBD}BbfuVP_FfEMiHm2mRM7xZK&`)?z^l433okGI%3fx~7sH7g4TUSKZs69NH9+B- ze`rKZ>pGR;IZH!J#L401LHIg;Mb~V2SA)(p1Y3P=oj$S8p~$KGt$v2Z8K?`v10gdP zXcPXsKuKPa5ckhr+Z|-N)PHuFoZ#!%dSTW;MNN$mNgPeyx}^U>?B?(!N^ea=d&qv5 z$w`i_XAX8Dj~$X%QAExkXykXr>XT$~ZJD<=TW?M5O4U^B@tX&o>4HpxSIR2M0eL?B z;{qD3I^n?q?00vW-tbbzWuZ%Ur9JC8`I*}v(6s&BcKI82x$J1^g`2Z?hwnX-^x5*C znDgC(y3Tu?)s)5L`OAdj%1bJ)Ve3ZpSR{R<_rC7&l7|f)53Z4ih(?w#IUlzeM6ACz zVcvo}r@KLuD;ni}kh2iij8nwbaX)Ws2agXbYMe5DF5?d<{7M3iWK8rSM{~y#H$>lU zR`DBmXU4>$H&1$ZMHUu!`e!$e^C|?%)w7$Nw`hg)wmLnOV|{)r1XW}~nD*NPz@H~O zNXoYNL&w6M9e+hP8BU(PqvCROcZjIcoKCwm=-2+OIItJyMqlgPKZWvm%vpVAemX+q z$opzZ)n%RMF3o9UKVUz8jW?$GnJf-%lriRBd53dHHEEq za*68D+ma_DBu5?i-m%EKMph>MLeSvMFD=^M@!?G+npck1k98G-3QKZJYlK5iSlhl4 ziI)!?zcs8y)1Uw9Sle^OB}Fu`$m9O4+ja-X_@N?a<>u1KVY}P^S`%^T_Eiy~__5bA ze`9jaX|{8F&bN!R{kG)Q1&z*ppC+QF!~5Uj?WL=N0mGoormr$H9d+4n%kt4@TW+n~qJ zX6U}rDxYB&Cx-K zXDEd`@0PEP_lf2Eyl!Icds{?LIQc>d{amr^t;KAeAFE zK&qcqfRw+Kuau9Jv6PXNp_GA?zLbuXwu2N!>A7-Pln0ZoK>iyZo06ea8S)IlKi;lW zprl9kVNz_Wm`O>=`?Cb{%1Hf9`Ok9#B2K6pgVLsq$iD*BWo9uceFnv%)EN|$lC3Ra z!nGQcQlt_Au4oKYl%YRIjUKhwLvX#WP4@HybvgQ0c&rh*`eOp2EDI$9)01q%BFIT$vREem$7mi&ryKXoiL za!H|HL<+TPb#iZ%x-1mhye5vSG(`pTrg4<1C>C3va*(I+PBd>Bhs&fW58g(OB9#oP zrR-6!1`N1eCQli{+<;b*;202uFbK+?cZH)WLs2HYc8)9s(<4tA3+`C*o^h~r;B}C) z2k#q479`Q-ORH-^Loi#ich~Jk35;55f%9{z}=irqqs}@n3{1SpTii+TG=NM8REH)cEVo+N2l@xv;fh+$A49dMLfk?0`z|KP`%N@GUC#3Abe?v+O z{%2Bp)l+oI7RXYsL63@5jG+=JtT;f$SHRY>-iIa+A&oReEL4Jpl{8WzR0Wh{RmHlT4X^}ZWhqqriDCe|9>(p}{kVyx>&3xB)sGZC!bxG5Ky0OQ z25f#?T;cNa6t?RXk=uIJq)-{fQB;7P%o_{h(V8>lO(TsaycW=qg`m-$w~V%C>jY}$ z?IfihuZ=EGK#80#(&a5u+VLK790=|ubSQ_W%7R%d_s1*vsLewA%9jB=X>nlI%Kz6Z z&i`{IP00&(UjS?Zv<~L6?zl@Vb&0hR*)x$7vIZ)@G@+#kL4#mOTM8vA7^>jKDdLQf zGBg_~Lzrw;flbjtN|R1XeVP(`wkUVuK+kq~Z9P0t39iXv>B$=t$iWJSC~#UL-q~NQ z3N>}!zrcuCG1wW zEhpacQ>?EZ9P~kog3Y8%_3FBaMO3Cjs^0&N%2i0^);$%GfgdV47Jj^>2KX70k`ueu z=eL$p$rkXdl6)Gvv`m%M5`O_LwWwtkw7C67vzeG-@s_=Wk2vbM!04!mTCNBO2~a?87Z8qh{@FR zg}!{4Y$Buh8wna+1J-C0M8pRH!k5X85b{-tG9=x{yI@hBO!)frhuuAZNf{!Ql`_~A z@C{&%Tw%PR9{l|ZWoC^m#TaQJPyVwztY>zl0`B@MqA+4KTt@(?FO%w{f=0OsDkS*q zjq+NcjVr_}ITnKid&bN*toV^H>N7&yphLb-t04Bin26%0R8ifN8wxq})Y%K_=dq>)IkNDYK>A-x=-4?=n^ z_$BLdJ9QA4HytGABCRQyTHIplsE80Y(2!=*(wkl03)%yDYhdguEd0HvPKXZ;iA4x$ zCM}-qa)Aejo6fw$94>{uord0InQSS_iCL?TcqK{!)P<{GKydrd1o|2{g|EQ5yRu-; zbl8;0jCq3g{rD6}m&&3vDN__f5vO1{lVM3YGU4awbWvCmX_6t4yTB_{3l7Xco124UqELFxjw)V967cFr6L*CbhJ!M%O+MP#`sL z5dbhiTqTqn4(x~%P~vSBNUq!|xgv@F_5y#k?7ZhV{`K)r zW0r6UKi-MV8ZlwK2oh_nBVU|J)^8uvjF-UN)O3(;eCV5;Flu+e0(=qgXQd;m< z(Cr&(x>mY=h$9P$tuMsVY^d`Nz##*g?<8{b{n;xD*Z!H*JNqzW#M@UsOMd-%md)KHEB7p^ptKKLg#I6^7d%?vo- zz>^6nRypdRU;P@Q3ugUVJ3+b0K~QdY6O?=C`T<)(d6cF*Why8y84Ai36nmY`M>7F&*zG&wr8sAa8&0FE4(ZMGut z0yc!JCR9N+h5A+$<<^kIfqqzU*q|-$GRP4^Lq1WPS3@yTlX*jB5SF$L)wXD9tb*he zC@shYVQ>_EHYomjxSr(h5V?8X-vXcHAMlZ)LiUKJkg>TAFxF*~0g*U}o66~D4LM9c zM;l_6xv9tjmkBHwFEI`E%_BmMt=iY zO3Svt0@@byo)jg|o6_kZFubc_gNZhvBPih4pKC)=`mp6#n6;_ll4DWEa77F>q}#P_ zwwUy;<$$iyyJCFiA9c}#O6Km`cwGRvz@w0ZUT6&D6O2#O| z5Dibtj|r|zj}6Kp9XPORRS78>RG|i#T5|}_OrT4^*|O=*osS^2_At~r0Rf)33MQwsm9VVMe@F$nPJmm6Vwt_1(SLt9DlfF{X}1;7 z1~@6p;=!N{$^J=;ouGv#6gC?=E3>hgbh8MP9*P;_g9Rfk6bq@c7*bTEatKXhf2>mR zIfClwfmkwlEhPjqv|3P|JOXw#+};E3SQg27;|Poy=HToA&LPZ0nHs<{Q#N5LQjKtw z5+U%4X3RQu$_X94bZrtuzLd8-C8dEqf9qBkR8Foh23PU&>7DeVY+3B6&I96K^}N~7_mk|3!~(o0pph$#h2nlxL`=B0CK~!g@wzoB0roaOAQ7X#E!(K zVT%TnAq}ZTof4{rw5YL>8?Y`=lcRLGnI5jl$`n|MaREPo=1m>81KCD2kWGN42-L|` zB!~H~f`l>C4J)3ouwV-j`zJ@~q3-mts*P1cavBx~c0@%Uh73bBfDdS<)L<`yB6V5t zp~s>W@JEvs07)sq_QxH|qmwn=wL;SRR=8$UC!S65R`#MOHU6pJ zR->U3XjBV%7-K($49bXTS#Z~rS*uN1p_L<553E{tRweGbW3|WcccXAP0hkYwHaBc@ z=p=E$s%dA{f(|vbJSZv?4s1-RJTQ?sOm$)NU-g>MoQusqbhD}_MHSW?K(jl2lvLRp zvdDT<4jVWMT~-dO)|AReoDJ$K2uZb3y*Uueqg+a;MA$v}VM3e;(1B7wr(|0>cHVG< zEsCqRCmSlTo5^Yo^P;F6I9I1T>5dl{uk1S8$aERO-X&LvAdK?*pzx`%Dl6b<0q=pU zV+6taM57R^C`etcFc)_~a3%_;z^bKpzbfZXtouu$ApJ zPzuZ%flOpQ(UMf6=}{q)sAUjIc=f)>W08=DJTm}I61dNJMKK=QESMn!+TUt28A`ZM z^|2DiWO&0zodMAhnxX&%Br$8PD8o)|7{dT)8G>CoLT&g33uI{WgPl=-238Dt(g<8t zaiel@V#s{&OO}g#9bs!ZlEWb~_*0Z8JX9gs0vpr^6K;tMIEFqN<;@7d zJbNxj9aRlCao@(V*t#UDqU{PBQXywt3ci5C6AuB>J<#Cn%9j zb`OdRDn?7LNLZoIk)~{+40kI*7 zQe<=Cg#+5Vf)@aRRB$_6lZZ?TR}uDAM=B05^<*A#fPq2C>KA!94$Z|(wmIdFu_}?< z0TwBd8y7Y`NHyF=i8xXf9D!m%ZNFgP!Pn!^1o3pd%R=YJCPoN9Sa?GV&L)vLTTCg$ zoGMYhpf6<31QK8Xk80(SIokK3@Q__l25^RlU}s_U*uh1B+0#bV^dt_G9Khjv zN&-hvY*^LNOtw0CSAe|5fh&@@CPU;wHlsSuB4t2v*`PUl%y&H$VXkdiKoG}-*{s2- z!pEBv!P|rSw2blSZ!T0caB%vlP-SqRgk}{qLwrL{ef2|;aJ#U@9X?22iqs>+@KAq0 zjK&h1b%=lt@GM`2b|Yy_N_1r?xEjo&xPmJuoFscE9^luA}Kmr;&wFHlsxz)xR(NbQ}N)j zQ6R@i5WBt?hwih8N$FF(al~}u8X%2iaTU|M*guM*bn3$aK!roBpu)if7Zie5mc9zdqd84n^%_hHIAc6F1cnAXu}})`vbD&` z0(naPZ#a*PgchP4a)rYzios#-;1KZ?St{fQdCk~tSaT?sjXd-W>lr?9Xm)tz%mnu^ zhyhn}L~B?r=&ZV-=vp{SLg<8Ys(-tx*SI;k}YWAwZ&4DbAuU&UP7+S zS{2YbXtOVNVvpT9qu1!k0Oj!}vmpp`Q>4huNRtVGwF9ict1F{+rE#~bP(83M3L_&& zykUh5^tu=HPs^6XZ2gR#M*tD{vQfe-#pEO*NNhaw)#H9*L{24oO@+mtq@gxvjAQ zNn?wOq@$CQS-qS@Z!YC7cT{k)r6P@z<=aS0a7k~veCQ6c`_wczcJ|RrWDyQvlSN8} zbe+#$MjPT#np(waBd*{C0msmTK&ue`<52{#bE*3knA~LaTN;b>2mtvwU$_3duHzm}Za*2BD@=9|UTvSb@8S z(<+JANC(rTjb>3Ckg+!4165jy)!jRdAiXaUo2-gp`x_Ra0srVm5hU0uk}gid=0qUL zn;*}~5|J#8$4SMlR3kv6X~145=HieQ?y*_rR8LBdzXD%m2OGIf6CzadO?3IKS_o>lBBW#kPCaiDTK-k2jdcD>ahxOf#9iGHde8WZ4CpFbzBHL?q{4Lkd8XaX!0(zgK92PO^;qP2Q_b{*Ms$A)I2E^+-TI)u2qxEs9ECFNDIgAcg4}7eVqmY(Y{O5A@c0s)e#8qOk5|fcidq+p$FXPj@E~`C<2LZ zI^9WP-zmH&t|<`UNHc1xg8H;DK+H9LL48&R)!Ye)=rx6?*&`sL8Z{aqLIu=dr|s@X z`Q=*Or}+31W2qQpFs!hyB(BfMP#wZgqzdL!Tc{SSCxf(y>hl4{3Sd&6FZit3DiABt zpBc^Qx*LC?t;P?F?tgXCa9iC9?%9l8BrK!d#Yvn-Me`{v@bCjL$AQLrDvABsIkrA?oOcAo$39ii1P8t!i zP1=|$u;v|{&eA@}X{Yv-j8ps^r@h)&Wcgb%eM#2;N{)M#c8~e~L1oDq8{E@Gf$`BD zEoOEnh>`9rP8Ya~IbGECA%CO66QvL?kEA0lAbk(g#35a%gwFVCp&SNNJQUX~ zDX$YF6{aHW z@HE$0L`@B)Aam*;&DT2c%sBxC+E{;Tl6_L!gG@*=cwF*;NSb`xgP7n9~NxUX6qWlN-I+E+D$l+F!N}fkhu8ySo-O zm9S2-AfsxqR0<~MD7iXYzjpFYVt($=tB$a>Rx;kQ;Iia^RPIqq7v;1kD&_$s^*H`y zslt$m!0ih4>ctIb8yPTRtmEgPe=2**&^6(HI`OPDAz!DF)>}hh$MDS&q$@udE8H@c z{RL49mUXUJL>blN(6?VhSGaJikcDLvA0$;oQb*oFFPWu+*c}nF21ruaPfR`2Nz>wz zj>dF(s#FKsM4_1q#KJqblda^LO9n>*7K*X;%O$HF1hEbq9a9)=uR2T8H1g@}k5+I+ ziR$RuMb`wBr)bdsQdAN-?_M@=Ipnbx+ah*FMHju_i9Ml%h5lc->687J+HA+ zQaNZ}M>dbq{XdBE{c^~CK1m33Rwvm6k0~$jqP_z)a>>UK)u(bXq zJIFCzhckfLRgK*$*)(aa3Y#b_OnVVK>44)AWjNzxu8VR2rYts75k8@OL!^Yz2pU;@ zEZj+pu2yM1V0RlkGa_j??R=VmMYoNtxI*%b!s}{LTC-qj$QT-Hn06fw>13O@0%{GT z!|GS#Kr1O?wq6n(=!#EkXizcUp$WIfJb5~t9*t5((1!1&;o7m#<1v)=A`a}xiX?F6 z>j98fOAIw1;6erTm%O_P9pei0yNjg`M-tk0qmAFR*s(kGK59s?L_tw_PQ?!NwoL51 z78XP<-hCqnpvW(Z3KjJKu3!HQYhbU&`ylsTCZSm>uQQ7?XnE~LCpqcM;enX}-xjOR zGi)Lk#;DGplO+>kG+}yKlS{@91cVJWd!a-us*ac$g$PEK{a8*V7H1d-WQycVI|uR4 znZ!vU!l4n<>NAOZ-A}Z?lxFAdk?1}bZ@}>-Ee)Er7Cu)t`JMb zAOa{wsr4<@f~9JS@^{fv+K_3j7_nBo1%eD~wS`*CzMF&=xj@$Mp*6`cNl?;3+Qme- zVx|Z{G!7gQCKk@g0T*Bd&?VheHwSc0+&IEi=Y)R)o7;=ceVI0AOo`2*Xu;-)RfXK# z0|*2Dg}QzpHuwAB%|+6v|9f+9qRo-{<1nU_r-b5c+oYR&5NhrW=2#o#r->`vjht?D zw{p5tYO+h*b2z=ty@1oD?xnK4QubRX>u+ZxCJwx+h_(vdk1OVyDiYtUC=a!$MZ$Ei zkTy`N!IA>FQGGw*G+gnBa=?XWB3o8sxDtlfQZY?D32v%sCGdh2*udQYDTcd&Uf~mr z+FpPp_U^hF@cHc3Wo851`FZR+FiQnHQ6!Cv6~4AC3f!R@V80YU#S{Ufva16y=Xh(wI0z1*tEMYqFOnrgnmx#e|A2yT_`I6CK9 z7S<}@4+5cA5+|0S73AX)S$I0K@j|<#`kE(qe?nlwHpJ(DtFMEMOqu9WgHvW=7SD4KS-U* zV|6Meda;9ygL>{0scfTwdh|&beR5=cF}#U1DOni@ugQA`pS$;(lUw=_rlc33N-`sC&!X>*Hk)fQpt(RT>)<39EBvw&GS z@C9hks>#58`B;cYB_7ctEUbh?V3ZPrQ%k^wN|t0use~$2&4zISF~~R!K%q$co2lSd zj6%IT!YJgqV?-f|eL-pJG+|%H5^A8DKl*7RgsYJs{g~a|=1&1v#@Zk_yVYz2^3I?9 z(}Da0ieg*e&M+%fDsl1nU;@EorSV};da0(-QEkU%hGnbKb0&p}ntM7O`71Ryt@?nD z(Y3H}TV+H+ykILftC*rxDYg@xJ?KJpI4x^@B;lJeIwjqLO;&0ia)4_m19xElM#DEK zDmuTG=xU~RjU={9LT?&21ceDgj&k6I95lmr3Owx$@>uOUfqVu0__!Ix-1lpPL}=u5 zAu|d+i}5;y1UZfr0v1hxP8KRsTd7_|xPk-47*WhevC3C0M`t$X3Ve0UqZ(|?g;TZH zUBtC4Z1=*3iQJu`d11{$EY2V!$UmNXIwS*$J_uHP&540&cxjeU9B-i=CyarLQhESk zVY5|0WTyejeCvaW=EIDROwUo!bG5)h^Mu)KG6+hDb??w2mWXwVIY5#D5CQI*&XXKa zg_|N7zad~C4NHv018&OlVLflGh;G}gMC$5?X7JmqWsFVUW5yR(FMIN7^tmSSi zP;08l-K0AB>QU$85AP&#T|j%aXorc@!1=XbO;xm$Hb*(`q*!UKwpvuB)pj6BMBFuk z0c1!ST@$Iy#3=2wG0b8f7O4-5)pw`M@Pt-1+Rqm`vyU(}SNbBeAyby={>PPAvjE7M zEC*y`h7GdaX!3pF2$|G!j~b`vXYDoeEf0%)H0re>bKx56~*IZcN@hQ~MXc-8Qs0t41}i>NO|*jFqd zou>|(&Rif6+pO#cNd<2NBFiA>8PvIQs~RQySSFrM}5jI;+4W3)7bx424hkihWGsYL{n=ZrV_2t4Q$krbWW?% z1(sLuAl*cJ-sUJ!+8hHM;;%g#yDw954%9+BU1n8MBlj|1XkP6gv2b@3(ZKRZVmZqI zwZ-(1amIF~FOotA7l8rJC%qrlIkAcz+a|>n)o>Yx%E|YMoV*u26>x}@Ya`?VhPgu} zz939u<22kl*SeqH+6qrrhLcoS7jHqS##iQ0IaLGgw;G2~>fUJ-X1O0Q3N7x3O=soy zs;W^qVifA#kBe?_?$x-TP?I1llEwMOMl0b^$a5eI*-KUIP-I)ty}MbWbmutYM05Op z5+c>nN`x`pGitK`bT&+vH}!N0zUgef>9Q0!TYsrLd}+WUvS^_su9k^!3SxR${0pI&f&{2h1^gu>wyDp?(7}Fc+$Ugk_JX&;aamPld{Kw^%zwvcywI zkZrQjwSTt6t;7UH_suzhhglF9R^FGmH}2U-E{vK4LZQuQ&669(Tq}2Yl!(KaNO(r#*?KE%$X(Us9HMKt2yREbbbx9< z2cJ#}51pW)MBQreP~Z4;9{(Zpc;6%yJjo53q@B1(=t+#3a(Jfa17|X(vnx2KpQ*xQ z`bV0U&ZLg;F-IyO#Z&)46+Zgp4?3lZC>i;Yk2B{61I=j{;R*NNf#| zwSiowb%1OPFu7FAY~*S!^lxDqE)%rZ>=yAwZkAHxq^&Ggl?-KullbK_T%}n_Z@2Oi zHSTb`kmk{}xv-1@te4`>v8zNjR)n2KV$bpRJ4R`~P#c|CWvzFw=v8Y}uY zBgb8f<$7hT9Cy;I*ezB z*w|7aFo;~54VvM-`y!RFtN|SU>T)%ljlx*kTXQGDwUlGE#mCwm3#nozIp|2Wj9;(X zz!VC?v_D!M>y;Fsm6OV7+a=rhQjX0N*x@eLaKTE&32AjMR_+e-Pms}TT1Cq?%@ZC+ z?@Jh^joD(06gP1#C+{z2K@*ZyOI1eIRcZd+JAq+0R7Nq@ z!EIX!!xDgDc|b0Hq~TbWTM*2QVu~5{utwq@J0%EN6Dp?Lz_D2ExGK_7nLZ`4^SaR~ zN&6BiVHie$HYI8NKo#k)s1YN7BO4hof3$CA)ct!f>Lv@+ts>xBmLfL~xdxfbM2-== zK_K=n3%#X_asY6;WtJ1ZeIR?^674XsFUoEa(UR#(xswFJ3Op32K>;*sv4c*s(MgQ1 zRSw`D5YNHVqD=no``3`r9Cz`vS-^?;ze%WkHDdh38osh7YuXhjkS7xPi9rG8jW z)@29L&qAi3jrtof)ie@(@P_dwn&Lq{$kn5jr|bwKu~kfB59%bA4#JAVN}1S4ChZrT zUXoodMy6w1^DWjWr2<{j@#w?kNx}4Z3h-DyupRUmPG$$uO$3m2*7nWl!#LH&>>6b{IWlJr4=; z@(fcW$|FW&w&$22FVC5&$ZNVFuhk?WEu~KJi!K$GT-2?H!?h4~TS0u8lK9ds4F-9w z)gHwQzb%lwRC1zpfRs83^OQChah+~eDN?%7+D=-7(&3_9=gkPs^D#kao=*a?+6H!k z&^$l)BeZOwut85*{^XV8Yb}tS9j0Ra&4_Omh;PttCO%$}360kxX<)UAWoFA(S=V?o zG8`-jCc{GHijXTn|1#u?P*=jOs4JJ`Iw=_rb^=<91~y1CtX38e?vY~AM1}>n;9Oyd zTuT7)%?9!H4mfG@``mwH>eK!#NN(_zSxj<+e-R`%_)pe_(!5DTa%mtrXM;%>@;Y)s zW(&!A6G%FFoZ?+@{uB?!iCKAi?)(c(8+cFi#CtH@vT&-m(>n7fLX7r`p z3Ykl{tO&qI?@ED>-VKH>l<3{aLiy%PVIwS8KXUEROV_=NnQ5SA$3`&PnUK2blK_J5h%0I+b!~gQl$t1nd=-- zbX;_Rn*$C|`@T3p?We{8#%X`EGa1Pr{)wSum|B^2=)errp}#u04jU)z6ddpNF0as4tNIwg{!i2K(C=Zpznp@#JlvmWQ9- zrQ>H4lfpWyqJTsHRHun?sa60DUK4!(O{>!T9^gVZ?GRodVDbYyf$z3@X~;GC@V#Xg zk~N(I-{+`+hI4^HcN(GCmgm|C#~1pP=HzvDBw3s7X~5g=Ey7P#6$1M|l8*AI#@ui3#ZFLzW&lsF; zXX=)}hn(lGv=;&}?z&*eX7J)(V7uw;<`bZ^@CdCpC==?2i&AKs<7Mv9^VF8{%{2-6zuKf7#|e9=9BwJI>%W}CKP?efL-E$i8k?h7Nrdy)vd#D*oxBYq4*Ig%rk&sq zK@h2ey+&Iad72o7SZ2NTLHV`qR(#2pj!%9qyUTpjBrR^$PEtX8nmW-S{F(z^DpFiz z79tWP6`>fJzPf35b4bF52>i%bbT-z0QH@8WOQm)SDEE@-2Y|BaejCGZdzs){HCFsI zoEZEn4JN<*LhUqu$NQi9Zxiua;kG=hoC{y;J{Y6K>1|=F@dG>AHb(^S8waG&Dq9i= z0!0j*3JUoy*3KZHp-9D#LX{bF#&-@;`@Zm87G;^Ws^>PM^;+^fuZiK2jCG0KSC zAe_QIs?%^JFEHGd4{A`MdT&!8gxjPL?)5RH#%?5=TLn|71|rC$Re~VF;B8B) z@vG+*{x*H~YGzNaZOq9!wnz9{ite))fG{5jrps(WmmMIX&K%}HZabtdRc0%-AkKw> zGWCe$V{H8;4CL^Q?S!rrWd;dRG41>GY1@KCXAU#Cr*&Fog*z=sU~10=5v=x8onW)* zeRP85ZEAzHaJR(HAa~0#TWp@9{mkcXS<`}K?M4CQtuzPqe>uK+lfc=2M^(wU+A-SIREX`9L zn(JvV7+Pc?*VBF!48*_dK&&%!J#@cs1>vgu(rwbfPMU>utvg)`j9fLE`G1iRnoG6E zAuML(+6WUCQkOjZhK1B)a;%Ce7pUcw(8|&_L9Wx$Z&(KId3O0Lc`H;GueU0KZ+?BM zWRH8RY`K$Kiu_vkQVZyDACZH(rQ7Y1W4r;g-RnLfTTYR-Iv*%2TkdmTl`Z4c(r0RM zxj)P;+3u$ZzN%@qEca*ZTUaVS8xlX90zdAyw5Cu_d%;3DaiaoQvw+$yb+Ub?r4@B| z!EjHF7lwPbCD-Yr-PPJT2*dB&EyB5(qbyG*bH5@&*{H0Jr(9_SoyTe?wU%#U8qK3tth0)`F1;>EM|X$GwsClL$lGrHi4^yvkf*{J9t}2HafVT=BW?OMhCY~&PE6K1hLVWWMKRxJ^EA8$-OLhCyB1E&$)Bnlu6PJ<~Cvo@=KCi1BSNr&r7t`CCh2k++7h z$kVm=NsIitw8%ecw#c8C7WvnW$~^5m(jx!S8@0%Pck34UYm$>FCX3vi@CGgN!dth< z>+BJ?YLU+lw#e_eiA7FFIIXvu)wJ?9-Bey+b8y8XlkLnE8_njmc7Z_t0BN{8VX7~) zioZBPA;}rA){E%e@#`NnaJG$N1MdKmZj*o7fbT}@%^60HrW%#bZ)Ej#RXQ^c5_hdsGUm7hgxpMT|FTVH+cGxFr$ApVf zyC`qHF0+a($?aXLNIx!by}qD|K`+RQt{2T0T|bo~GbvKjeBE#dU-%l}UEp((7ZPc|JJ?%_d#Au0+~J{bstgzT9LUxlT2E2# zx|3P`Lv%CMo1sMGl1ggNKbVDdwfiShdwy9h=Bu7Y!t~56#_>DonUzA1Jd~Z+pA^{M z%}$uV=+1N2wivw=B=Y4X{UFOTJ1A>Ei9_7Xk&rvxIZ%N3$ z9?vDCGRrezKfpI$Zx2atPS6{)>7~dm07cbFib}ThNovdlHL_I87gB95`ZdXZ1)|?P zsM-zEOfI%`BDVx|S^bc95#YE%=)Q!JQPIYem9>@|n;Z&RoF7hBVl6l3gBbG=mb^() zZi;1vyoOG|HFU00=Azsx^ec;_wN^O|1Dv+FP$gGS3n+Yc;CjP?WzKx#X806%>8>DlvX7OyO*%VSi8f{@wIKI_Cx7%njjO?i|=J+0JTG6F;qM{kMVbaPD@~Ww@bb1grkp zL9J%?l;x|-W2RIArnHgh0DAj(_}U2+R1{|`65_6SgEDokaXw= zr9jeFLmCDcoIr7J+rcR+DHNju$5CaH_ot*f*R#Irag+mIjHB zT1!J^7_B)x!;EMo99Br#kZsu%%9I_RCGcvvOPHIrz^ma^23`g7bLPnbhHhmPR=(T7 zAv3Q94-GJW*&-W$C>Uvy4DJ_X5D!0!9nKi2leSZgvUvDi!MKs`&$kM;!HOzk9`)eR zr6EZC+;F{btgsQP)%o9WWZr2<;@rdiV;-PWlPv}N?Zs?+xq}aFgLQyit54yqZp;?9 z5swk@VlnkSSj@X`PES-2 zU_nTRgDs~K7DkGAe{hsMR|v3r@}(hAW&*3HS=s@Ufz>ldpSC&lot$U60oIT%GtXv! zuv*Ej{m>L({gQMapXp?`l;h@M}En)5ZY=N%c0%Vtf7Mjr2yIg?PyY{B&dKq@g z_M5=fyGO<=_M719J#-Uv^`7NvCr4NB#7*GpeP1wKpPd|Cz3CFJKWi6o{gs649|%TB z|7?cqze)ku*608=-YVcaBz3qUlMa_Rlq%pllzmgUj=~fuCji6?xR$s=C~QLw(!Ogm z;2J-)NQY}mXt)lolhaNnwTA98!jnS6b!cA@T!$Xh;hGu<*9W~X3AhfuUEu4`d!)_u zA=SmxeT7u#gjI?G+@Vi}MB1TeC2+sVz-=A+mZ3El4E<07_h%u2YkYYmfbgo_LMtef zes47NFKOdUGhmxE9M2lTv{SLYyItGyuas=q730iM+UiVp$I;Q-n%n-IH}>F<@v*QA}U{ex#Hb1O2I z)D}z#S%MJSKnUF;1~i^9He-@l(ky9l6dK_GRqmS5v7{|DPt7E;q;m|NEhv`swqWaG zhmP;{=5PQfz;aCcB3vEM=y6rvK8BwAkTf!msW98uxnCjRt%DnO4IbKuvhe&E=dUN> z`4pZR*WW4NyO52MORaE*B+7fC5&*dtk19OM@F?(kZ;SBgg41MGNI!0&`@QsHIEJT% z`^0_2bSvY2hAIKIFHt91S?vBUSGK#qZ}d!Y%llIIuZ*7Y?!WQtrh39TP4*;kn&8Qk zH$fGg#(Em1kGmv+MeV=v{NA-i^p z4TncVdwl}0i^{~8h$|62G99`5fH?8U-D#ma{&eKlS_s0$$Ss05aHjMImRK63e|oy5 zQhturWGO}N0r(Hqc%OfI2b*aVb~+ewzm(=AO>H~kEOMN5hMS$@H+YKh$j2kccOjgM zM*T4ZPM0oTo%Z6S8QMp7fNh8AI(f(WE{GC+5hMB7bR{-DogVVXJk1x;lA9#rZQ7-un}`e( zWT37Ob(N?~2y(8gY?>?u;I-ia?V5D26GAQ?91ZxKl5&|gJ=X;vD(8B9xi(*}MbDW$ z@`*M@?vEg#hqa-O_m}6ZTjbD3%tKE0gWOi(uYY8q4Sej3TMJK9>h2=nU}Liq8P?lO z7v4P?`a`>(1yBAn8F+pv3C}OkQ)!TVZ}2y>nePq0BCXZGsx6rIqu#o3ow;cr?+B7P!%hj<+Q|m z$$o&hF+LSf$`L%N3w)(r@|7~dS5|`mOqcwpM)03I(JwuS|5OS7bBBdsl8xL(@SptK z*gpKIng0;VZ!J@(*mC>&x{b zS5OR6-#WlFd1&yLAoZ zQc%N4tWXm_J5oUepS9F7+%_ z$wQFIcFM`Gv>~XFQX23@dI6NbVpnNm+39OsIdkL%N~uy5zQqNhq+UGuA1JBMtyaX@{c4^# zyWh*R`?D&*@>;l|d>#sGhjQqoGvzVI9G0lhn307@(AC$X@?i9WECqEeUhhixwzZX zh!`csv~K3%HFDr4W8I3w+w9sQAj9Duw|4oSYUz`1KKd3##)4%FQQ3i9XHYy>zNH%d z=AyMpwoVtVtC1^pa*n1f)rPb&!o9;DlVHT5Z)d&QMf=+VUt&fwwQl29iUdPzwvq>Q z+$3`e$mJ_#_!IA|5C~S}qSke?H4&{WN|S`{J|ixKkLU2?f8ghBa zr68AOZsnJk3PFcYAz)LbD9D}m=vEx<0|VMIsSwzY%!ufRK|xR z<-mvK;((8q3+L9+YH`3v8`LcH`sC5wF!FxSW?T;3SU37iv4%%`bT?MkO{}%Tqe}z^ z99<_c;OGVu1{~cgFyQDtCTs2JK4FC&eMDfwQO#t99X+9nkykk_Kl&E?LZ1Fzw`PS+ zx3o`fQ#D0lKTikRRJUq69hIijQ8u0O*b_6d3w41Gr6;;}E7aPinz z1uh=@rb!b!_EMnAdh92GD(kUd^T60+uSkuE3$F>}J@!und8?0GM2O;X$E|5e(=B}l zL#xHz{qf|`It`uWmPuLL@dAO9$EV}X3It9b?>2BUKl*^MplQ?1SaQsSTpYU zj>!eLnfvvG=6=WB*njOnyAj2B{E5k<7$qk57<_QkzDRISwrZ~(J0-CWa*;9Z__GTb z(~jd$*kQXbsND4vC!&cNW~ZCtSdag>8w@Z)e%usb7p@&5=^ zI}vWMy_gfRg6*A16_|4(-N2m66L|u2PL$l**Gtnavkc6sjKW$CewdRbS=yvXbD~Ee z&58L&aBK95+x?KHHjt48qKa5~j~}YkOZF8COPT=o6N4coV}O$;6oQ<1JP1Kfd?Lhm zM1dZcKm>`$sgEB291vtB*wS+nLr%OTTqGxcE->W8Z}_aTPP`Is{9N6MzjuNcsgf75 zrk&$sNM*>C1zOX^Cv5^>PPzoXoQyZ&%gHo>FDG*he3^c-k}Eq;RvSIjPBwC7+{reh zXT`}ruIxHF-{_fs@;0uFKe^hZe4X4ZaPQ=n2!jWn+(SGt1w1fc>0ust@&V$3sb(H{ z@?jc?2|V@~W8m?ifhU6oUXTN?8q9OX$+y^7F)*eS>bU~jdte*3A~zR!-z4$ALRf_B zkt>wBT1(+FZ4`jK?newRu+bc)0EXTMHuOLn>m+R?gEorD@j$tyGDkc*fL>01MbOL1 zZyMj=N1uGnk6v76^UG|FWryIo$-ZJX_gPvU{=7L^x37#GrVQ|- zo(f@TasLdn*<|M2oj$_ML|qA5WiHTcI<+F`qrX!_W?~Jra&r9ndZ)jJk?(8GH-Ge( z%g(YB-vcS%PQ1RkmL9WU?Q||6e%{$4e4wY^-_8Vn>d8)|>rQ=K5csK2s>}>Ndv+^= zb3XnVApsNTD?sRV@|(XZ-%nDuv6hDiH)Q!5YJ9mWA6F>B!{7>ezPbWtv3eam z;UV0unWu!HsXQg(Si4WXZV-9K>2R)0I2~mWdF$y+uAFx|+vu5px`->&PnVmtpVRF` zz-b`hLS-%!@afJ7)_U#65`BVzPcJqoKkf8JmF}zHNUBg)ySVvwawO%O24Fe^vvP^AnxXNFAZWZC1dUhZ5`Q)E!82hrFarbSOU0a- zMgud=1J6W>foEJMFrLXEFs1>FSdp8v2#n?xGtU$WFrFzlf$>a(N*eWXBDGo_1Rdi>^U1}^vpafbhX5@*+$RKvqCU0 zIBOEjg=Zm{F`~`1&$ElfKF=;O?epv^vCp#`&{MD6sUj^nyT`7*2GMx-&B3CvP>99_ z_&u6B`Fk|gmQ?wpv7MGor?}fDAYvUy8&R)_Z zH}miXPZ|P3OO<+P7V}BcD7CoMTj)@#lpaXxRtGsP8eKG^k4NCI9Is({j}aT>h;)oV zKlr9)T^iM4W*3RR`O*QLWLd|~UT6c$SQ~IcFOa!-noN^9Yz*21IGq?l#`9ALKNeD#T@^!`6wp%PnG5?7NVHpE0%_sYLRtd z()&Q|cTk=l_vk3aKUT!E&qXfPryk{+6(yPDb!PjkTdBeQOm%6#T%0eLWGG|$d`1py z$X#*29)CAFzxX`=eoL$alU{6UFM|U={v}grvxG_xax;+2_WiDLu?)$P$6ke;F~U#< zjS)saqt2MwP#FzhdZ40ctYPkF_SfejSL5F=@P<~#?VL+sqWScI_Nr7f-Nj1JxdW=p zcS##gd)D3YB{n^`#g{Ae<+4N66^E#+@a3{X^veqxVKL=$eYt`V*8oMnTv><_%h|Pd zV<|LW?c?Gm`P>ieB7F%dz4}k>(Omw8>ALycuefsNx!;f z_%qQRcy!^<1NG8lHgeii$TrvOEwdNVqr09SJ$SU>(T;`=zFmO&-O@~t_745-VRjqp z+Su4`6FT|%q%Nc}=hJ$St~;MCbn^3sQYSzEE7Hl6uMaAQ?R~yxCRFlLsW|r-H`$Y` z&^hNj?5wAq-$Z&^CiJutWs!@Q-b{L0mRV0bf49)n&fjlR@XjBgfrS`YrEC-f-88Vs zZ{Q(0@R)hv)xeA1^W%XRz31N{2foid@ar_tg@GALy%_ic4UF>}_Cm5(#ifFFl z^MAFkfgW-GU%`4r1HQpvi9APqjjtVtu)nd}xPV2j19G}El$>6~M)rkR5%$X>j}Q|g zZ>BO2!n7gaHWi^bo2C|n7xILCeW6tNc-G@>F7)Xid9c(g@X57GmQ9o0l&0TIC@hS^ z{_oWH&%C)H1m}*`bAdcJ_&fg#nq;{q_EpAge3C23$%0NUoD(siizGwKQ+h6Z#xLlk z#AiHLg}5Tj2;djYE}8`+xbS1UNPmWuCjKP>9pzt}xW$Fv32t%W6%)6(@F!8o17!}M zk0*A~yOju&c1iT#0q#KbPsF`d5cfr;gNgg1wTp@SVuT>>i!qY8FSQVHCqDgtQ}E!$ zj7ku9wTxOx@jViJHggUaC#UtSixq;_FSZ4Slw9lx3@N!dR}j#}MJCF-czfWDz{NWP zZv-yhBM0s>8FLp$)F>L*EC-_ba72vXz|4y$d7$g!IrECo1O~BO{6b(5%f;vAiZ7a1 z{6%0m$HkWe!#OU#B3CpUte5P8Z0S-&AX~cR5-VOxHm!K6kXBT&BDTuS#k8W+yyB%w zvErpV4Af`qR@qFt)MwuZwsdLn6rYAcS4XZ9xjvaoMozy5mc~fF@Bz+6YZJGEWi1WG zvUX|{MDmx2;_9G!8K@Xpa$w-Vkt+IN%i&e0V?;hm$qZW7)(`iNbmZlpB8OD}-( zLDNBx9u@~Zden5#qsL9*o!aG(n!-EdM=uNa^yrvyPmjJuoZ;xZq_n&e4fpho`KB0+ z(U0lg=^QB;C-otZeohF*(H8>w{^*N=e1G(Zg71(1%p@>I{}MFtZ$Sh9BL-dxH}U-| z@xrflCDq;yEV>fnli+;8_veD2H*pSJyeSlBHM8P*rCR>}DDz~>t&_RwmUUC3+m%j% zZdc|SH|23xZnuYyq077(A8m@lZuZIDNd9!K%ib+v&azw0RM7(;ZIQm;f zzpMKM`dxk4^y|AyBJ`1t_)Aj7?)M z;VKwQ6t04?G=WWHITD-3ZilPDj7?(|(o--MHsy>p3Tztd3&f_e`GMFpwoG8t*cuZy zjcph9_Sn4wo5uG3&)78PePh@(c1mE=*aZ_djX}SJXY>}aY3#-u!=|z4ZyB4$e&ml$ z6v{UC`YmJAc&uHd@tpRIC(+xYoNB_R@eF}YhL$fvFf+p!AA?Lo_hWZ{Sfm@Dv8>m1F!OMdNQ3(sumaQz2uekhZr2EptOl+iQd& z<2U@!G6mAMSgFCEH&{G1f{uSxAn5puCTTnVdp`tCF*){cMcPhG^TXE^-93JDX*-b| zjJa9Jl}&-e6Q%yrHbv=~STG3=-#3M{ow&m;(rrj-lDh~rDDN;~^Td4un(U(D&#QU!>jR5MJa(8YX@&ZfqxhX}YnU_&ryqO#In&w?6ToK$N}~ z7KqZYkRpe`C7lxv;5it@mEN$4NdiX3Kf=aK|O6PcL2#NZJ|&U7zj&Q139$P?8;e;)LS zJIp^$5qLvXH07;Pj&Xlv{_~*a9B4gp1xDr1?x0CKl9Wgh{nQQ)(Na(7u(F=&+GVKY zTdw`Lva0}#poqf5vEJ>)9=CT#;{hTe-Jzg_g`ybP-Q9s_F?%SO*xg0h-QC^Y-QDf` z-|Pip@qOIe>Df1LUQMi0r6z5LF=;c5$0r|!DwTR^$mDHJP8z#q=I;D2n!L{iXih5C zzI@7|E)AJlWcPEKBJwpsrcL=6$Ei#gz0KmA?5BzprA?J5FAZs*YF_lxkg4UVo@E!m zG-Rqj<)c>fIQ!Jlf=ffDc8ib8@(V5v8Jj#GxP8SwJU`R03S)1kRbg+YQ(^DrnGNS( zxiZt=;S?1Mu3VW>Cuc%4TXGGRGutcd&Fs1mdzA`%>jQgL{MIv3dh4YY$KK3g3VSn0 zC$ZN#bNZs#o4JtcS$=Ws&0HSGUdaON&D^vAdoxeRvDdrs%9WWKrp$Fj9tBsebUUdP z-Nm|4+glOK>$l&!c#Xf_YPS2hdlcm?xhC?DZHG?J``?V6W5M_jy^8y|1a+c=% zfreX{_~uEyre|O=)PqU_I{mch(Ez^6sHe*-G`&--=G!Zbf-A{ONkq!C45wN=r4bF$ zCIsD0nW=sgjkRdHNfo7SNe2#4;Re2FtLW0Av{Ofm8ax_Uir`Oeu7oc})oRgTn!FDm zPDyj_Wys5f*g`&MWC}0&x8>zRY$;z=p@_T!C#2+uMg@(D2&BttP2X4)cvQXF@=76g zmA@Dv42>UGF;Tp>S5#g_52w6ejNjpqI8cw(5kC zC21!sD9a!zB+^A5Ua-)kd!VV>2~I6a>l}KN>RDkgnu!C^bg`kP)9QpyS!kvIC3%y( zL|#pM8L`LA?eI7VEx17{Q=}i#Nw0ykg|+%to+N#OBz;XGfKX>B6Us`rku8?;P+tq} z>4w8C#bEWbMQq_3y=Cg@c$Mt|Jd;*d>pt1I&^qSL3Uc zjq+?7_qC}zcqut)6av;~6mn;|pR8u^3Nbq8Np_Aq)ZW3MyOsO3QVl?OwG!^gAV+qs zSI42v8oX$5JJlYdTJ|u&zgjE6LNLLK?N9kK8koz})p(%=HW|Kn)Y9z+gD%4h&}%TQ zh2^zqSoGJqonF7Dmy5IBjzaGz92TecBk`R+EGERdTEE7q(S_3B{h&dwoKa#KdQ zv27!Vb}Czkz;e4~WML_ag#@jq6IVdb-C|?R`5Z0kQgdhxO)pN9=VQV&I-}V{lu^>f ze3X)ftB59(hs)pe`?~+E#$bM2@^66K4*D{gab;%1!)ar6!~!E?qt4;3tdc zb>b%{{sY~PtvdO3iGm+6+(~{KF@ZJtok?3r(C@W9oYS<@mj-lOdO4uaGD@ISR9V@E zKTRG1AyV#)qHvK_X42VE!~`^s>9bnQu-F_iAr+Htt!UD8MNF8m1;V!0Qgg}Lu!iT7 zwPng&vUWCzHQs>ay^TQH{`e|w&`I=C;nc}o2490tsyTFG1S1?+A3lLTop^f{C8PCX z(V!9j^S~+A!$1`|5Aui#9F2=VEW$LJQ5Li0KJS3LH z*rsnXgrj)0QMtEzE6}GVf2jpDEJp)}EmsjwYRgxs;)6@6`0REC3mO$HZdPy^yIgIH zf=$aQ*j}w*SA~MTc6gP>DtSBE{??G;1(rOCHw;1NFyJ`>i-HEF5ry6XCE-xQMkyvk z8@Q|-1;cIBN!8dAuN(43ogkf6Tc#-6R%nypwtm8QIq4Zd@RFc49a{MX)}t(A_qU!hbYOVadL9p?7Fll? z@(6i1smm5NkgSRksv*S&HVodNlFBWCZ!lv%4tqo`rbEE7yx-Pv-J;Jq?1O$5Bw{D7 z?brvOkN2WC)xmzZ<6ux^wv$Tn4y-1S>>6N(O{nf`aWl4$ViC2H7^`4d z9%~<9o)%kP@wC{=NnX~EW=#Wc^h68o&tEPh8|dE3rbI%rEK&C z1Fdo*!-qfsdRVpFD>iWuepYb^q~=v`s8iyd+hio~U}fQp+)a%%B!%lz@wjw(l?U9-BO>Xfc+;aC(@D;@vEc_ql-Sx=WFdo1y+XED z-b*IQL5353aoK$#!4BJ}00iwgC=zeJ)3b>Z;^P%IgX)$O#Gsl|8I!5Z%GP`#ICV8tee;UJM+D<5D%zFbR2 z-h5j@9tL6E0nSxIf_zcJ1fWRSj%9a_m zZJDE${v}UJwPnsRn&pGEHb7F@NwTFnD={CI!ngYKl|`SJj=la(7(Xk@hsZ{dSI0$p z0H$&cGOvnlZn>yq53v0_By7vy7uCpy&OyTNlz^bJT_OsUFla7Qpb7@TGRx8cEQg7c zh3?wJvPLb%nyil@*0htD$F?yZ0-X$eJ)s>4bPN!iTRP@Hkj~lNes9JSP-~VzN9>>6 z#82KoCh$*wA})fT5J(b+6^~Dn2`8?qE?I?#WV7`QfK9h#u-{G$*58}KChBGqd05oY z0dJBPM{FgJHq`81x2qUVq(N(A(zcg@=I4WEma9e6gh9*`vQ_EsyR<7lz8UlJjRKHa z^ZE7$?FNG`qfkD~W_L$JMj2Blnb;1IG_k`>dh=*f&DgkQUAJP=vNl$0W3Wy$&+(0T z5C*p~cslQ_rt{u)Je?0rCBegtQu&AwE_q}FbCGPZIvJFTi!7V;M77Cd<)hr+ypEwT zsYQ40!-kj_`ll&s10>9wAo`nVN}))V?l34jl+k>+O@c1XP8ke4mZn{KBL(XA>$OqI z3Yhsj+gBpnaXl1={8aOvbS8*wJrZckk-G#K&t=50@}3-Xri1PlVq;MZ-de(N258a) zK_2{gHE78&y)vMNc;Tt>kjn+Br0+R#3AiTId_B7ZFf7mM1T2#0uEuktraAx--$1jV z!M-@%cEW&L_~c_G+Jma+DywF^^$Qi%&j5yY+ByQ->y&;5SxLeJYBL@HQi3-b|>FPqN2$=~YdasNt3! zv}@lB&XErWk+m0TYre3kkWZTt5J$=`+s?V&zBeOb`?Z7XWk$)x zxiYM-AiXh$7bCHP99QG#mCx}c=#j@5#qxQioI)ujU<(2G4zm-t#v8%k z{VXp(U`ey0{Isc3z9_`965rc%rIK5oHXH_ylGB>}(lB=%24J>j7|g+}EQ5WwCL381 z*h2K`h;jLGO?o9~E3}%GW2+op&a_rA{Gx*}mnKhkM%&19qlf0AL*2DLw3M>lHmU%u zv$i!FdCQ3IF1cp&Snn0PLT(C*`?IsLZ|LlwpBJcMDUcRoW`%<^7#8r zK5Q8l8_-fc#qU>?PddK!3>C~t6wFC2*dSkpMERg3u7ks`LN?PD@D?;DuG4nxrzk!x zuop*`phFMSiD`pz(3-qz0 zpTFjtYXswi93oRoPfTGHY>1T``2xmOwc%68C|#PK2230AQk%rujLP`BJeM+J%dy3t z8|z}2A6ubb#rHI@jEwcwUw4{UZED-bR|G%Z1a8y19{zA z?ts`;iOQF7-Y6lnJ-F`pUa)#5{l^Ju%RE#D-% zm)FGUJ`+?K0ln0cr^S&6R#->e4bBO_a?h=TX56r1(H2P@ys;B+>>-x1Rl9r(V*DvW zT?n|TLQlb&5>l!F%PUDNdG)Qx8q)>OYWeZs&+0wp+vw}>hCM|Jsju*0+a0b%-XMa| zqZ6&=X(ORzYe0ZIxC{3^2q$447z@8wJ_JDeer5Knq=naJ#l%`VRKWbS+;pd5QL9W; z=roHm=)E8lu-2PnwHaP`>fC&lKD2dCE0FKNan(zSS;)RL8uQtSSyZsc!j70M8@Ed) z*o3t)74f7@_cqRmsIeW5_zJ0 z7Z&r$R9Q0wMInZ$25z^th)%^)V2dvJx5_=#ZZ@X;Qs{ZMhX}#rYt$1=-qeO2w%ars z_7b9i+QPtkd~bRXQmLEI&GvVt|panJ*+0xqMjc9E_{8e zUv+8Ft9x#CkAJI5f!uv+S{hherBOzM%VH$Mh{IU0q$>rx9Wqp|dEtaV4;bi2o)r!9#SK(p-bW(`-P{mFT zQAtscKt}8g!v~^O-oWz=G#-pyY(QbxX>y_|2%F0lBhBLEYvS|Jv_%!O(oQ#6?%wSr zFd7Nd@_ivtty2s&7|W=)>miyVlS%C9p{0mY=w6}-#?OmUU>Ih@&h5F4JO0YT1>RRk}~_2Sh)?rwQ`?Y{h4VB$`6I8jdhqgVh5VT@SHA< zsJd7mMeT^FAoOCgAd8$Zl+e?NGrFAo2r_)gBu)!tFA0MNd=)&Zz+SmoMaOq%_S%cK z1?3Q3x2vm%c?_FkyO{=#*eV^DkkcI7$JAA2r1HmthUGN1JjQ)MzOjyTRVV>yNhzx=LGnM>bARfa!%0dwS^2XO_Khr_v+=V0~bnVdh*${bNzVNtJQCq;*< z{8fD_e-(!_tX2-^SgnVs^d39C=TKGOz=}H8Hy|xl;Rby=SGa+cs>Ifm10}Xb1ghL^ zMOEc)BPzoIE2#_z$e8NeIc+7JaVFE&jr^L!AO<^P+PfYMtO6i!jdf#zs_YTF%nMY; z#3qTqEmLK^R{*+kSznjA;8!-$i$Kico~dmT9CMx%ckPPM4GuDuo46}K`g z4)Zjj*%rL#GKYoMbmKjlI#)PsNmIe40n_Ubt1_9d^)Y)}W?)T#iZ#|?O?1uG0Jd9; zvy`p9IzY)ft8&hD*8~ZyL(W6~^jp%iYIw!>iVTmO*sHUj5(~ zmEXuuQ0NWQEmkMy4|Rzdwp$FvGh{W5FknD1>FU0WZDBZX3cn8rmxA}D z8xjaRiB#8!(~u5>rxl&i0Gk`Uftf4DQY=j`JmuqO4XO{5!i()Zw#Q{>#32jHLcgcf zeq_m7B$$KXY6!BDQI7q$oLY$BIv^8RzRQ^&>`y2GkqpUCF+Eo%Y!|BUfY8M9;dSI; zoNLmeB@=Le_?Eb|vZIZ5BB zOruxXM-!RVTQ$iquvy{KEYyfS0rqHbf@Qos7}Xo$DSeMdc-pog`pwyB8~G(|hqi7d z^b`OoVNeEkGwG0Io+xXIop6xoP@NADIe0SlD9bT;3>_8G|Nv*WBmDP z0QF!Kt9-~<2bQILHdDtGHo+t5-C-%VV&eI9?6`9tR6x%D5su3yygI_77#2!577wT- zQH}E;9Xe+aCDf*sv|)xawuKXL)h(1C{KxG8y`!IPgJ}P*J2??--$wb z*sxW>JsWMvs#3=C%PNK9$6XK%HSYu9TTeA%1-IeU*hjmlTt{;*&-PoXiOqV9oNW2%K}tiB%)m28KOAO-Wc*J#%Bso{?@5avj;WRwXFaxJ1QC(rPLfCB zq2T!Y<>6fDgjeM#H+|9-+;sSi(0+iyGk@QU;W;-kG|xSg)3eU|D$4mT@N>Sk zR-}maHGLT|VAF+stxwU%Q){bXcp;*~FD|LVZ`$FvmP7*^ZrKa4{ClUGf5 zG@NXt$0cf|wHH@gYDF1FtkKmW%6hHiajpduv5jO9c5EPedF$eMbc-F$W4`x(0PC(} z0<5G6)2FS;70g$XbJ}mVaT^e$*<`=H{;F+@%Y0gDK=Ba<8e4EJ*;gQ%^HPZ0-@}poM|QlJ7sP7FH_azTJEs1BQ~@BodcO zy1@r4<&SWzO;snW$eve4tAFi;Te47IYXZ9DVN9)S$F?`@-II2XCCR?>u^PO0QqeVH z`&Fr(Ec-X=a3V)y!{z)?6gyyba<|fMHUlUW3SmYzRfT@_5o@{lb=$JJQs_hDJ-lpq74TZsZp07 ztgp6#e7Y&%GO@O1=mVSi(*Q9?nwyU>thej_hhKV*bdP%Vo7*iEc&X*dU zt}xkU@dUM&=~Prv4BaU+_GYF5z1s<`$A@LYH08&rAh|2Q!H9jD=~9YEg$Bm@TTg;Fv)Ljnsl;nX2Ge zzAC5$>e3u(j+GgSoaJLRUOr|$*5v(%`-3vo{Xx|@9=G1SFD#7pdXrZGnS}H0h*gOk zlM3zhx0mIQ4SLm=yw~^ICs|R`?q2)gelCw*@;aXX^o517QFJ7JpSLRB{%>Dc7(3Ow z;36FpPl37jboVcQf&SQK-Z>ZO(?Qm;r_2R+a_7vwiMxOCFD#55exo~2G;U1nydDS5 zFtk6e!h|>WnIUCA?IcD;&>NG&f#8pXSDwnNM@$4T^Ne z+frz5e5Ls`H@?bznj0Uq3$B->xw7$1ymcV2@vZ(Fc{MxMs{~Pv@9{T8l@FqtLrUWZ zDN-7bdF@mCD1Yidk~A1G!nb&NlVE|ncpWmAV+4359|H`KB8 zZlHvSqJ+`0Z$JqfrclDf5vv1kIB~3^go%?F-FXwIr%=Mg`Fs+2$-kq7l8ISG2@^NX zr-X@H=2ODNJ!(KF9!jBvi5KQm!o*ASDPiI*yWj^&N~oOpOi{wbH~)_kjuZcx5{~mJ zN;oc*LJ7x}|36ANuKhn#!f~tqXG%D3!v&OZ+ z4mmdCQ`H#zjpmL0WR4p9$-?B=o0Co6)N7kDN_KGZv7cNq-rfqSC!V!M#(r|h9((&z z-{jHd1!F(C?cA}ab0(8keC!L8-)%@8d!TpUOHQSsUv@((&}E-7o*Lt!Uw7(gHS|*_ zm`h?K+SJvw05iBMDd0QGFX-326zLu#H*Y^%G+|>II zXZa(JzQs=U<7rC=(N8g+^)v^7*JG<|v3I-QD@H>65BBtq4Z{nL| z_0wm1`Ged4b~=B3?U2R3Nj80jR~@te`?K~N;$=~C?&p1`?@l2#Zhi67^j!-M6;D5h z{`VfzZy%Mf7lYG(#wm}y5T^a4|I?xQO;ayDEe2gq#oT#mD{hSMqOVH1x|hbuczG(m zm~PYQ%%>{?u0QjYqSKilOcQiEn?-aQO1*S#HoXqC+2Lc_#47UN$*zLg3`Lu>5w5gm zwwj5mceXZ3Y5B7)$}pT=E`@W=t~OuV%?`|$cC$l@bIoq-%}5s9dA_up-F3dSo88wg zcwmy{mCQ}E>LoBbZ=sHW-fSbZ0sFrZ|g+xI}-oF0tpJFdF2%1J<9Q*P;op&3w%Hb9B0#* zI(G0nO#|Y;GuN)YcG9d}rwI=b(8Tc`bL`CQ%7&yZ zUwAUkBKQ-)KTkrf)ohfkW>04D4Th1g zl}7e8SAm{|NfLzEsSaj~Xd2A2Tm^qD;^;bA1;sQ>gHIQeiOPqcCRud-6dKjWepC)# zK4VBW!gjV9wjmC2In9-xX35wS(#t7;WZDGbD7#U?avB3Tt85X#(*-aFb9qAj1)GD)p)pL(iGM}0T3})K}Ry$5SGVy z5y3mDg25(P9$ctsk%Mx$2q)?(e2AkkamK+_GyL}R%it^r3@)?$dgpX_IV!TeN49*L z0S5C$RDd!B$d^GmRxru484>0xzEP>c6Y7+bLT+!b1HE1sQ8*xi%@(>KDvqF0HjXDT zQgQ;kzyyrU_<(Qx3R<@xDf-=ASp0l8FMN%K?^UtLQw`7r3Y%3hwDWm>t{JYCr0m_`?>Cd(np`PgAK!b?>rFU&;%NXIao(D zD&TVtJ3ipruz$?H&e>eo5f#ty{G^P&!(8;RtMQHHov^05mbTCn)3@y_B z^!--2;iC#?2JZ7`Lw>MR&;@c?#A(Io(=_-X(5p0>=2@C8bkbTroKFJ1Ajvsd08Bu$ zza*f!=ONh3Fe^a`j{%clsW4I``$3Y-<_YZ1lhvT4%RJLDvZFf^Zy<0X^%TqT!N zoEEltirc6pp|yUQU8{7@3>W^-aW2Q*)n8O69(P@R3cx;tRi;Z z6)+JJ_RdhHAmnxrxz>LuChvFLCF}}6z-K>Po*lp62M+G`u>sIWT?AUiS19tRC}{}u zAFJCwCckBu%pZ>K#pCzhJL3Z+XgHrIEBM@vmmTYKqweL1t4P3+LKQhC%a5T5MsW(= zl2t4kbs1`rSrEcNOVduu8Khj7KGXNGP)%DlB+WN5AMwvv;m#OGtInFxN|V`UJziFU zg5G$5dVe*L?0Y+~BMm#EJlQYvk?i<)G9OLdm){PS6~0i#=Md#rc?e-CPhO~miQbw9N_6H%U?+*T-X%n~t;s`8#geli{;Qv{bp^ zLKh6~hq6+W>GCie9XRZghqtkaDOR_AuC*xdIJhwI(g&f=D zjpQF}5~J~`WRrOjylSIS+9$sL3V>37@SjTmx}Ob7^0FQEa{Wk z5*D`GU!ve$4ePl?$%qb3P&6!Tnk)#T2i)JQxk9i6v79v<&h6J+5ywv9dBT_|ET$d< zcD87M%6@!khC0Kpe|z(#NA6T`X#dW>3Fq9;TcTRD0xBf&p9(|oQ<=XPR>VQnN(Y>6 zW%*&E!W;E$u6*+~f0`=PO9%@!C01B~FFYsToQc$D&?5)X$FYX&0QkuyN69Pe1PA;Z zCQCd`gzA*r<7nzt%yO589;>Pk#1P;5I$`)^5I{&y0ynmAQIc2no=xiJyn}e=WAF6= zSKPu!;-p>>R5r#)-4Kiege+YoiQRdXs*sV0K2i(2JHj~5VXY)9P%#ch2CNHG8`P8p z#hWlrz*Y88$kLG4=esRHWWmDK&_6XpZoXFY0@ge{h6fnX&FCZt+jjIeyoUKSGm}E7 zNhRhAWR~3%IOAX|TuxSY_mign&30tav5JlvBu*5u-m^)vAsW|`Ms}VF-~(n4$r1ix z)cS-#a}d)Imh@)y1UiX#b;xNwk~*8u_ryknU7D$J9Go$kYodf|!pG>BGTFg+MPe;2 zytX2Zji-p%ru3xAn$6^cP{f`D%`#Be{`rc#CeVYRwb4Uq>{Pex)|M$Z?$r?iATno~ z>{1&kYK5Z;kJ*jCnU4H|8{-D%>@=Lw?_%NoFx(cw*$ZQ~Q6x@3f=e{!#YP#xE&*DK z!(tL*pfy1SyBF=+8J+(wL|ccCKdQHc@$p1WY?IzhDF!koo22EVu>c9Kvzs{L_e1i} z-DGiXeNV$16P1{%=$dr0)8|c?EEH`<@na09YN5Lo+4dgM{yun!iS`o!`!&JWV5dF} znbumt5}_o!hMh3+2J8YBL@J@oz;Ku|x@1VEy!&XWO19^IsM}Z5cn9=}Npo}!ydEg+1U4azRsLw)U_J4z= z*CmMRMT{i^C@4TD_HablWk8Vw54OBZ3)9DSy4XV%Bju4vxhrU0gb9OScG2)`-A39= z(OY(^3^5CD5K8)R8HC&f_;CG8q8zp_==Df5e5g@HC|J^RYy^K^s#oC=euL+$EOm8?1Q5nz=lKh?KCo~h zE6~>&RKWwWD)XZaHTq9}i!_#g;R7c8!NO=B#98ljB#9V;$0UX50W0Yt3tVRq^b~LI z+Bti`a!6;3JW{k`vjsFw>q9r4nRTlGp&>O39^u;`;faq$K+map9ZL=c8a+{yo|)x) zBZazhj1^-W*k&W?<3tyRLMFbV2hKp&U;`NsK9HDB!yU_rH_A70>n^@530lta&6AV+ zQqf|?b206Lw4cQ~f`idNq}OS-OwTAH;YnaquZBwyV2lZJWLJ-QRbfQ8$jFlqHb3_+ z0guuz!($7f$$#2c;Q$ZFKfi@DHHiK1)fHHN-sKlIfju{68IOI#sv!IB< z8ndk2Kja=8h0n+};Op6zw=u5gRume5GA|H73PMH+#d+{ppUa{YZmLL^5yN-=?C zp{KGL1KeY5F~FY(PPD1h9tGWoH7{XUslcPg)^bAw&^nYjV`ENs4VipcG0iN2s;}t? zHwUTm8A$BkrdoOp3=PDC#AiK(P#-+=6csAQzCTaL&nEoP--`NC<+uzqZJVtvMaO{= zQ0x~vJ9^DJvdGLj366o;BwVtDa%?rpU)ooo?#JuRDV9b{_~mx41hKx{sBR-gMBT_l z=PB*=zmsq`2LeAg&3NbGbZX7VU`a%j44AaC6L|8-j@vU0zfBHaR*e2sIYp z2m$MBvzH|@!lEnJo7ZfF=&ea1Mq3hyEy}q}rPjk~i`4ynA(r`?R1R~FYNVuGosIN!VY|+Y zbwJ|0&NVVh4%5_AuBW5{8lbsjd3s0lw)+YTD7&%bBQ;%h0|tR6Ruvv2CKYO;GvGT%AAP3ZFfE}-d4D<^=0OUawz`QY98Npp$$4nrz`T)!Ih+=KbOy*$v=NyiJk4GH_gL9|%oqjHXW3$u`0kyIdLC0F;(4~{dv^GF z&ixF668`QRu`IC7-e-=i;ax4xOnnh!qrK0)!_?E@V5a`|TOFqU_FH?O`dNId#%=K) zOt94fAf9I57WF*)1He6I8?>DI2%7AD-mR*y%gp8Y&fe$#4R30W8peqH;Hy>ztmbx! zA>_^Q9^oX5VFyr>9kF*RVy2I;|J^PfY}1K4@TGqce(0byKviR-!vO*cF|<7p6ewtO zI1pTPQXvqyAtiE1w7BS`$`KN7cR-MISQ-Gwfvt^;P6jPPaY(did2s+iA(sZAb4)%S zj}^sk)wq{9GdtB|i7+Os(#uAnHNaaAKZ?J+k-OFii_gMqbd*{TJ)aAV67Ybi+{53| z2d=*fS0nY5{rBL+>$cZ##3DF2kh(_}C+r?BBJhYca<2+@AU1r55@xU=228uc=QY1} zHH`PTJe^IBwskqL6dX~L!b~#DF05>J^ZAu^Ft*o0EQX2HY9Dp+cqDC!JLN0oT*`{S*bj>{} z!{Ku08`|&$9h3sjLtvxv=H-~Ksr7_wkTY=WI1x-Vq(w?&F43)y2_GZM*j3oe+=}Tr zxLVgw8kJz=&aW{iVF?XLg8$%or%Er9r@JMMbyxAH3O3uD3MfznU)~nNPNx5LToj3d ze1|wpTT8{a-#Q)vnnv6xzHPf}M)le?2 zh8{;-k9t!vA+u~DuxP5l~1t-t95V;V0^fQ#H^5VZ+$IfY3I~-7wa` zlELLwJ_}OC<`MvERkfnD3wu=}w~E2~Y9XDx1_8uAQlS{~QdDlQ_UdO=T1; zODW;@vAaYGAwbU&9$5bKV=CEXOb`H=PWQj( zXf@)V33(ahHQXv*L3_hBWkNi=u5AGQM_=Yhf*+PTFDD zA)^_36(TFL-IpN?en=^AS!XjT23s$~<4S#EJL|CkrihXS`cbplD8^j%mk>O5B!;Ot zw_ma)@`5i6I-E`!H<+DBkYFBa#Ij;EUqSH9Yufv^YKS)*I4|ZeHz7!LnNBz^bh>i#;Rdpx%8d10 zo`YJ47)pz);^hM7vKPEivfZJeg>&wzc;P2|zzb*c9SUL^czHOq)Nbc+l3jhe&Z8g%m@Ub?z{`a=w6W*!PwI6)Kf z((yjK{?Ni{pNE1N%8CTM+}}IUBZ?@c@=!1&XxKlFTwPU<109S}Ozu9!R!_G)bjFv{ z6}LGQ9HFv05cRbs`F}p8t zaCD2(&24c+4}DzyeWIH)WDmsn)(2)uF>(%M!=?|+0>3z%O`AR_33hQfn|ysxyL`@@ z-Vet}7ER6D4FNgvTSGSJ{tn>!o}9n5nI4odU}B3>f%sfXkeNK)KA`cTT)&rKRJ$gk zNhG&SFE6r9m9@)yV3-MACY?~=%g96Q6lh9wfC41fd1y49(?6mS&OilM<#DJZfc;&ZDUXj z*WUN44>;V>yp+PifY}R;J4ifd=gbVJ+TSe>9z@^CLc5c|qS>7j;mtN5&rOL0RFRi&+*~yQ5qUR>f|G^Xa2q zJ{@?#8#|QB)h&&S+S`g}&mnHuq0-I0LLHPf)t*D_5IQ>fdJS&U;5o+4+i!L9Q&n(- z&7MQtP;}|u%ZkE6&n53jXtJ9(+r`gw$vIUbuV)H_za&(%2x@#zAdo&B6ou zzXsX;6nZpx=48ZHSUz0TP;Ooid3n^CRFD)w*$P9?!2L+-(mvs2vkv4hsnpOCre!|Q^0dCvHS z6VmR*FQ!)MQJivW!fQJ%Tgs>1%W8bkx72bo1xuw!Db4~9VZ$3Ma0*pRlX_pmpX7{c4$#NT)!f@|ZPs`2&f99Bi1xnUQj!=ka+xqz zUh!nv+N6~tojd|k1;E6eE&)QRun^$WO4))3Su>rB%a)QPOt2o(O3EaRyW$&~F-j`^ z>=JU=mX^TdHo%+981!m(_HP8MfXL8W=C&RN6<3PTlBLJYW70e2^8)7pRjHE zd58KT#1&Kjj`qzV{cuZs^S>Bq)lWxmX?FCk!O)~lKfQ7t9vSJubH^3wWosA06I)-L z0Hj+JVLOR;j{{KGl0fBjW@>E#@Y&*OY7@^eshbk7$o!qgfBuQ83tzFDR8tPVabGRg z$70Mnmklfxo>I+n?9%R>3`TG<*{WVXId8qvgM8B6jz$PEXxE-{mb^L4;#0kD*I?ZL z3_=A!SQ7;Rw;Mn`a_xt;0|za#=FZbG+zVc&9uq;dTYJU=bSt zJS~$4W7f|oAJO*=(pduaENN%Bl0_~465N&ZegAw*OO)WDgjykDn?V>)um=wiTb5z` z6mHJt(^Uf;pgA6N75rjDy`LHs0$6cCOWTBvEMkNSO5C$x0AmIJ}>zilC-$AK~`dsrEp3Q1^*YS z_!3Bg3&Ix(zVJcUv<3*YSG6U1F9zb>{A)`4{^ozvPqj)jv0+(%nD3kV&eWgg9c>RL)yji>_kojH`jpy$(fTYO z<4t{dD%s08TJ!ANMUt>jp)5oVG8rPSh?Ej@1G)PGxBPO2S&k@#X7C_aS5WHQvQ1sF zoeRg&K`Uj;PRsShA=yUN19OE9VWV{$YmD{KyPT_23Kpn<|wi=wDD!}jByTSw6rTE-cvLqpFED^`H+8F!{~Buf5Vb)iivXWT~(FqC8|f zR%#BO0IAPkV#CK|s$MZud;Cd@j(fVAW-U@a8IO;CI~n};rmvX+4Rr0aaJjtZVT^}! zjkxef(Wcy(a#7HR-N+&w(qtS+Zj7T-FEhLdBEh{tn9>W#&?2Z&D#*1tV|D9wnQz03 z596~NA3o5IWIXop{nzuMq@_u;*?v=xDBVx;s|5e zL|&I)Wge|H?m7<*sJU;m;tV;krikY`nk~hOV+&|#-_Ygw1eV>jkao8EEV3h1_4LL| zXxLz! z4l7hM>sFK+c~;ulD*eGh%A_|)h|l_l#ali8!`_iCw@yQU#dCR}K$@~Y@W8M`fdWGd zJTT0lBuZEAD*GV=iOY-S`XYU|Wyb;U1 z`%>xGmo5dmzOS!FaJL97@Qjb1j}-DLn6i|G~c5huXOl0S#NKWmZbgp zmrj9{Fc+y6H9U)I7aF2`mgMo3oi1SXB2yFplsJVo{NJiJIGdD8>+4dV1G%BWUrS zeDy?wjB5m(>D(YU^)kgD5Fav7qX4NGV(LTPD={@8D8twby)Snk!#aG!rr1L0WUa~t z+Y~0!o^N*EfLt2vrjPY_+CZa(iwYaE<2DeVKDs~7lQ{B`VT}-Z%L9sTvM2Sor2YEt z$VNAaqkKD4psqbZs5Q>d$Fq$a_6iWMZ7O1B+Eoqnmg3OJX5&oVxbxhvgTUR1tq`yu z{=H_>QEwSVmZl5F_t#c=UorIU1 z2xZ_U%^49iL6H|DKCWnMD|_pOgsMx?3XG(z=BLEAO z#UeKFTqJ7aLeBg79R?*OY1Nmp2r1to&S+sFVsVZt6nwYnvK7LZYTGlxS;J)RFCzd{Bs?%0dxlEWBIaE_tISMyU6p2=WurVf6bm^p( z_Q?x(o`uHm*@UPK;7f8u`l-3#%|nD5>8VwHg`S}Y{>GHS13$yIo^+~s;Dy-c6|Ux#HwMI&n` zD1k;ke*h?1Z06d+*!=|XwlX6yiy%=x);<@kTl3S-dD)q2-|Or zbw8j8iV{+DY`R*KTluwRmaremb5JPTFFzGSUY_3Q8&dZjCrwgV9WGi$0VktmNs+;} zE925kC?OC&L|YODvoJ#|7x&e=;MQYp?2C5+;Ib^{58XM5q{g4%sKdL3voilsR}Ps0XcM?fGlIDnp|JyE%*2o z@_8HSYnj6&No}lpeTi8jQS?q?@cx+L`Vighr{8ttnvVz{(uc3|vwz^ve&%ubL%v0N zz5Dk0EUeN`A_Rc6+niAQt>kClsBh#2p?7S;1)5fP70e*$akO0`w^W+PYNZuLcKS*) zQw&W9Z1OiM9o~BL1s!(K0aM-qTjTGGSSEh4K@JjT{Ed{b-)bNB&Q3uZRssB~>wDecK;mDc|d&@8! zRe3?6^wi)qf$i4zcWEjLT(K=F%?URQ^8~+rcJ?V zh}JEWNcxQv>=S0yp&VadecDnvma{OPM;r3Z*%B*N?S7k)5QZ5MF$IT)tJQ|2I&UgN zfC^xpcjBxL+9=Q(xp$D-#Y5eW@?AWl0lF_b31uUBpA%=pg<2Z~5lCnEOfH%HOS&tR)v8L^_@rSVl2FZYfI#XJb)(I6DiLOpSz>tI$x0sOi z|3OdJL)H($4!Fb0x=P(Eb_8j5OxhUmr=``q6yQ@CDm8}jQ_pBoH>E^b}I zv!cuR?n@#J9v(sbTL+`Jc7*Nu1HbQE!gt{fCp2Mfx(^#5(I?TrYen>r;r=%dvvwI7 z@uH~hF_!^y5$H_tGNpd$G**#hm;vd(&@sNw#ai5-CEzWJk~xmy(BIB9^{wHNSIwd- z{@-KGI=5^GId^T5$4DEJ_;El9H^F(5o+Dx8v-`;FPR)*HerlvzyR8ZeQj2;l2NH+7 zW$8EO4|n0)b{Oa>bGQ}keS;ve8Z9VU&l#$T%zBM7gxNbnd_QTuvvZxWf8X_u8SY;t z1SjPJ8IDb~-FtWql3(j};L(x<7ESL-)y&j>%Nbe${2c5USjSaw3L!7u(B;v zm{xroKk>tH5}y|@oR?mpyUN7+5sQme*^X^*?j4BIp3N^@8ZaJhrFGjj+b?G7fphK9 z6{A{9@kd>$tAgGCQwsm=w-*WgeY3}lYHp8W7r!XBFgnUTDlRy$v{9+tnhUP-bA0)Q zJ#`M;X~r&j;LP6hRk0mm$y)I3veot6He|D=g^GQL&{w-MVpel-{)TgP4(ly1MLG7) z{cbj5?YO;q_y@72;5j=n3ovEm0u=aIF19>M{KaK#bef$x&3FCj$8Vb|$yDZ?=K^#m zB2-GcIaS<3nmtFPmt(y~R2gJ=Wt=ThA7*D=425MgmSDKRc`w-A$)P@0t)9{J)N?>v z+OdE-ofxWGX}^zsOBdeCm!*(K-_dE9Be_4 zWR(UCAN#`afW>~+)En=4maO4hfE&YNZ9gv**paRbs8S#dS%cV}3J6PqYRX`oeELXN41S$m_b6sw( z948cLEN@hT_oc_-OwSeF39^?9BQ%XibIN3)iC@lS0Y35C17i4kcnq7?7&g8brXUU% z#bzKBH;Iy)?OL}MAvOV3*JKI&i9^ygp0XejcYmUzkG@BmOl#8Kpj*&h_w#`Je3wh( z(yhrIaJ<#up1w07JwMshTh@b+kOuHsg6CE~H(SpCVAC0A%}#@#P}JZT77C)QO7RQD zC&H{Ei)Lw}7TA?Ruo+qNmaa>+Ns#3ua`J@P%(6(^l1g(j+ZTQQcXX|%yqT9dJ;C&O@%hGFMByxjS1$~Yk1RP2jj{_tz8oJFz}dO9+l2+zihc25)#AE7T#}1c7S>t= z*}Db7f(&iH;lv7eI-39if8A-6h>LveP@98-)?G=J2fu))C&9DIL(gz86Lc1Udm2{+ zbaBo(GMPV85(XO3dFoNriyEor#2by!EDVPrGmq?3X`w0Q>rNpUOMUOiQn94Tf)P;# z`eea%Aw3N)Gs@56hE&dE4i{qm`qeDF-Jk{wmpBZjN8o2VyVp7<4g)`BmLDh5mP)Xi z#FFhFX2GlX2^{yY9-NRYg7*m>T2Z3V`J0t$@kKCoWCSQaDepoJqH2D(<$l6)0(_(l z0u3L4;`w6!NWw+%S(2Q=;qXc=14-We_%4Kl;=P6uq68T572kxSdK6_{kNYr3@)hE^ z6ioST?Djdg0L$u-!?+D2M$X4V2j&KQgD39o*s`>)RN0N{y#;0C0XfMRe#^e+l14?1 zki(Mq{=@Gsf&J+4PeV#`j5s)UBc79ldL?@`v2O(NYCnivD5;YL;Zk%E)FY;D-J=5X zdQOd4U?@UpD2s^&k7LZgfvLPxu=5ZmXPLPfNdWVT6l+}f0nTfY!d&nk?W1#}mbzGG z(WsSFN{VlwqtP~km%k0Atrsua2$Y7*ic4Da0@bD~PP~NN<%{>Nv&vNbOZ~I|?qu2< zvM-R4$jJyLGBRyZ`Hi@KY$>C*apWIuXJ#3uXcu2+lipHwORTYD&mPLHXj8DfvWe?V z)U=;DGaTn_CR`&HYTRbcpCfOS+;}|1_W1wqjvQ-aZj+orPOx2aa3A8nvFP|---aej zeWPCM#v$Z~oMptYi%GS3d^|AKCI=Ph?;l}Pk$|gpwk^>!l_7gr_;(%)?-Y5RC5UjV zwiK(ky}M2akY^Jt9_XcfpqK1G|Gv~ZZkzANPL!R6I*-y$;;0V{`0yge5$}DjGa=l)we1JY)5J~3O-l>jF2$SS06xuG27>!4$i$8vLkK4K#rEN0DJVI>T#4#Cy z*HW}zR9P>PBsJ3Z8S|ddr&_qGWP*lqOA+J58tk0X))B2A+IF5!K?pvG;}E0c#Q=}9 z|9~nQ^ythJX}bfs?2zq3D_zNSuS}j~Hz|T8%Q2LF)x57^yj_VceAYcKC_9KX)fQaX zxbg$HhimPtj$W0*QC2Eew|I@VH|3^D=#I>Bv+OvU-|6{tykfYsROU=fhIjW=O0&fY zeWdLp=I=$Af@qJp&1jfCoXZLTjgsrvU*9}C^vvJCLMZeHlf94N?~`9!Tw(KTgWS%O zzseh-apq~|B$dcfPa>7~uNdqg;#h}hC8xfHV< zxEuk0*PZ#Ujw}3+FTSpQw;tJ5M5e9Ob1foYOo;Smd9gN`3jZ|3q$3C~$f4;Ci@q2v zUpTxl8H}|j>2fzZK4?}yo_g3QI9?b%C{)~}+bazQcd{~LloLSG1ufNDn7+uk$-5-3 za20_P%X3lx0>|Y-g%fEKfC3qnW)UX*1}e)uMzxIVWliM3`RKk#>X=oqWtfTFZR9cp zDz{e$goi>9r-J1RYILLqk>Us{xR12R6{Lxc;A)<*H(Y8imPM;qIsB%ePUpgEr*=t#8EUI{yru8M2tuMMW7|K$P z3FcOE9VTep6JY$lwJy>U*m4EaKB!xlu%wZ->1OwtLht@|fBxJ48Ax^yqu&&hOg~Ff zj_5w?)KBtz4KHh|LCNtUZt(}3_F5D;D2H&XTMzhZCiYDFGSd4E#`RKnQFr2Q*^*7D z{0OUS4}?jo-2G$_nIzFrc!Z&!3K|J>!{9LvLLBa?VDfrURGKG+%g@3;^4Sqm6--_aic0gOa7prVC}i^K^K_7T zJt#JTHJ=zhe;9D12b-t0&#}?$K$u+O*iQwK+{<|&OfG2fr-Did{Y5vTi_3|8`fL-= z(KY5oX8-H_>ST$v@uGd-C}}awcXTp1&nE=dGonc>#kqndfSu)WxjRdT@mm+~ixrpv zA@7mTq&RBxw9c?F&%t#(FqYe8-R)e<<3ZYb%g;;U!%~{3d_!)7#vw@}dUsMye)aFz^?lE3OoWg%e${v%!&9QrEB>X&0HtRY8Pe#sLTu-mW zqyl3%IYsFc&*Dp69WU(b@OQhH8(4z}>&ze)F@x~N$CzyTQ>xZ$odSz=i%8)Ts+QhD z=6fF1*8f$K*?KPB99P(0Xr^-)H@sv0vOY|3H0amVB6lp<4b4^qo;P1WmzqhyQ^WuH zvpW+yMkfI)*@!LD>3Yf5zd3{{K@ffL?J)I)j^Gu-2-VXf95I3nV#vYIk&Q&Ila;>5 zoaW7Kw3U9p*ad_IL1sIl80yCb;8(I1q8eSzmaCAXun;jsJsVBuw-8AKLDW z5UvX4paR|lTySc(GpOAIVa&Zsf!V3l0C76iKn58i>AjiT*nsrji!2eDwr~cPyyqG_ zAzU7?-q;EUMLQ-czjvn$H)`WntoZB3aQ9Vet^yDeN7(i|`P=UJQr!=>_cn;aRfun$ zb0<3#5(KI{9$|&%o&(No-32cI+es>dJqFE4@NQhiKQCb{7@lx5_e68$7PVNU8n6c1 z#{9Wn#PIjCYOAJ7{e6R2($P|?Tv9_Foa1?%+}pYYNlL>PEbuC~mU|UR!E^N?Iu381 zDU~?F;w;`xTj*iKexo8CUuu~!LYs+o?6T<&XF9E$mzb|N)zbY6=_Bpx`H50NAPHvD z2=lU3=;~heRpabC4{))7fH$;-NMGnk->M7&WbU^pINQWniHCY6!4BNM5)`7xEwt6x7ab}J+X5N$d<2r^B!dLzUX(T;K(KQDk+h;+S;_HZ3jwz!uEs@$>acdsSpTa3&DlwmyYbfnm&N&no7nPgm>AXOAAFv%6Bkg@8fmIG*T-Zrrvq zl)C*eUJ&7%Yhq3O-9|Kcppcd6Dq^j)xnlZixO^4AwWN}pgvE>pf(OTdQzYyE20iL` zXMNR-#li5TuCp^TvuHFH4XzukX$^j5x9XiAa0If-J1SJJm(r4&Z0R?aMD~@EhSk5v zB_~TSm1Fy)NqGSs=`qiw!3%t8Y+1M?$T0}|oeGCPfi)E5!z#y$#fC(EKpS;H7%= zbpX!}I}JWnV6~34S_Uyt!IoBZUvo(P(AD zXe+L!I-%`IV(e0J5{GjY1!%3G6gTA3l#|?|#QUobm8-)Wv|B&VSekj3hw8=h=C#_oBC4b4E3mxBH{|oQ zuXqdI94-eSu|$ZlwZDu3CbVOuFTMk5b=E2S9Y!#Y&|?pX@E176%fL?f@>zZw+*VdWWI zsDHZCF}iU8LC(1QFhHjN#U@^;IHTp_?hSY@Y-Bb?;(;m zm8MuHvB0=O?LYR8bh&vN_$r?Mp)hI6&2S7uxyw*spui7KHBnlDYX{4w1crBKFH4r4 z#B$>F0A?7zwzhTbu2y?5*bE(0v&Y-t{S4_YV0@D;y>LGTlKm@qJ36B7BZW4ubx4+@ zabHM1uZ4^ajDNE2^XTw%*XK8oY4U|9j8@p7D5-^B$UYD}92MMoL=MGB{daG8(c$b+ z(YeG{PNE-dViG*T=S!lrSnx8(*dhcP+ZHi^gLMFD^QxHX4N#tI7FY8=Wo}Rhr;%s>rL1YyG2p z&E%EE__z|aB@BF9!nSC(h<+(MZ0r2pYO&A~3m@xVA!fNyvsy%_(Pnv?@L;yqrY3;Y ziU zDs7oAX?KD@qIe&Lnr9e}46DWN;WapqpXI*eww^;9jyc# zHDx`;ZC*%nKxTACel4qUW>`*@;_cwW9ppSKyEY&2qsq*Y=rAY1%(aaN@?~%^xJT2x zHOVH~R0Kcudv4~qEj62&IdwQsaeuILe+1iM-Fe0d56xI%!Jn1r3mo!}S$2-eD=t7= zWh*wf2!IwM1v;O_2m!?Vo&Pvq?xNL%X@`{PR8VQwHaQG4zw|et=OIkM$}24=y`WklfzSc|X5sGf(0elKGMkt?lcfi zHKit6cy9?C*K} z&=0A7n;JHMNM}LPgLzgbkCAY|SAWn8dx8RyXNE&y_<3=j!L_1Nh@;vSo~IFMi6f$Y zj3pn61SSs2q>hy2#72V*5`askxzajoP{TcPh_8lnh#_@;zIuFI;$vlp?KgI>L>iLA z8nx%djFluAx%Kx_t%}2Jo`!yGsP5nI-u$3{-^>w42EZEWYnY9Ae^1brvLLbLAn%ZX zWL?NDjc9d2?3kV%h?~ideMrk_c?UEiW7RolT4?QNQThmgSydD|D;b7S;$EOwex+F? ztt{;Rx-t^Kv@Bq5t0fTA!pj+`+IH&Hr--zLw@$~Cl#d5W4#){lP%7761pPNYho*nm3}c$wArQg#+?u z(ksl^&n)mhedI~`7hG>&{SgiBzX#c7?_upi*w4y+3 z)d<-}2ZNd>7|6npmi4i^qGJ`z(Djv)z(dR81@${ya3=D!Py$Mc07$NKK~p%JuAzx6 za{I`FgPJEWOK{l0+2(qwGupneIBUvEf&ebJOii?tu6U&xhmC_TgI!KXi7tw~urBi( zjq2Oif)@8+E>0zLbl}}t;_qe58wNtY5HmM<1`vcy&O|5VWs5{%#M#~bD1=+z>rnX3 z$il@%Ec+#EtAh}^Nbb}syaM>Vn9>I)D1dE>LXVzPpdOq9x>7PM{sH`sM3^Mi*>!m{ z2B0nm0!khas3OtKC#px0@*hm1iOZ>!>;wTDCOa}nsk~d2jb?1x=4%~Nn`t3I>L*tU zF)q1kx?mN|xzNg-PEEwh2fFOeorEXiv{Z&uBvzoU?!>A^ojsbt)l*>|S(dTlyj`10 z(4iBJeQQ!L7I%5A%XZ`pMW4dIAd*TgiJ}Fzj@RxPaiQA;#Pr#(_`{XLG1$vZ7yUX< zF6kYotarTSBh$uNQ3~NkwRmQP;tjP)dSBlr=#Yh6jbVo!;o~x?eBcW2#bz` z_fFYN-#Jofmx~@k2OaUY{+8rhH_|S0Yaf94r%k~r(P=R}j15g=?(SB05R;A(^cn0i z1syzs!qLq1zncjyA#r_>Bejvk(I^#UsMppjfRqgt>G< z)z~s&X;XZZ6C(hIg_6+p0l^)yVhso98Zw=*C^h3?>><%@y-b6Gwu4&{_a3gq-=QX> ztmhk*%~K8t4z<3XtfsSU1rw4Gl;vbl5&vniB8la9WvFO&JFqV@9FZlXNh5+8bq!o( zp)Hi>miwP3?!+=HinoFlqWF?E-L!U)+zh6WEm5Waz1Y|L|>D{8UU16OtN-KyaWqo_Dt+~#`HYZWM;gJc( zcjpHn$f42=#Tbzu6$$E$6I9oD-7qbW*NWpsLt|t|Cbsb*#sfL?CN2`gRsClt2=Q$) zpv-#^uKN`w*wF8sv5V9;ARpChh@95wP4<)ED95tw_t83hYcg%y<)>9pe_RrSuC()P z>Ny6p=f#{8+FYrCuJ&bJVdW-xndr)fpvUm{an$1!AML{kUEPd@HNwh{U}Z<1D;CcH z2;F%sLO3xd`5dTHd?8@1)P*hc9Qj2saK{focEu}Aqm?>yQB=UI!P3{|H0TA$g}bzP z_WXBL{O8DgU{tH^o5?L482sI3hB0#*|K4op+>AKm!CkodL~P?p0`q;j(tB9MSEcL)s||e19De0iC9u$wUvZ@@ zeh9x{n^3lDKewE&6;3hFA^eOQ4X|#ZQYVSgnOZ1xMXDK9gQAVg-XLi~b3PB}8n7Uw z%8nzFa44=)Z!bZt%t2`BERr13z)qQ@VD|iu@4FSC(9E1sDwxBi_f&9Gjbi4Gq7;@A z*Hgz%Wryh7MwZX9_ur&i(Z5nI%Mga7+u?6j4xdSN`m4&MbMy@Z@u?+!B98eu8}AmC z;&Y#XWvimd!EnwkK^)DXpzKY5#5j?it6#PBth2@J^qL@hx)jKsR;5W#>x8@0UjWWO z)oY*5W)Z0>z1X~bBhCmEi6(iSYXTHGX;6WAcBDR0Uqmi@pe6JDmaTFE6w*zc>YrZ5 z87Ip3i`c#LpPEIbW6}04OLi=t2{+`lK^Ew-+>_i@Ua2x!XvH9{Dje6z1pY0o2*%#5 zZiP*ewb4Jzy=6Lm7S|~4IWd2dT_gq02Kx|3E>U{P5l;dYHtZNv`(0}sCsE|pvD5m{TY5vKc9dH(dTU=GITpWbdXF@=&(!VUgUj6u>A>WL zxi*e!nN(>}xMe&}Ci91PTECR)0|DY977*-`5aHlm?wJ!S9R#k2e!E6@cA#uY_99zR zXi*N6@>>m{I>BqMh-LHWMKzb`HoINN(81(Y7HsfJOnWuS@$(?w1WqSi&YoSzh~Grx z8KRkoa(w;}+QU{PZ&4QlruQU?;a@`o-DbQE)R0O#L_k`5s{!1Fk+FOr%j}J#+ImqP z#5*_&Jx^MnJxbQ+0z_jj{Qrq}bmC2#b8rh34uTdZfF#Qq8*M{ctdpfetT<7Lh{20X z@^TCCUBQZeV3{LkMa#7!PCuK_!&mnIIP3^A{9+>+ zK7k(9 zp`t^xXkwSg)tNj-L&Sa1xQ?sB)7?1#2&fTvHum|8k5y(2@%mlky|oDAasMr7tJ|6L zzfxS4*wRB|bKRGhIr!tvpYdqjm>OK!uyVP7qpat^=vE2@;Akodr3K0grr`G*TCYlu z=*kso?}%UE3`ptG%K;-uKV%j%phC}llA9`Zw|*was&KxYyW^XQ^@`HzKK=Cgg=c|) zK~%J`8%pDc=ZwK3$w2~Ybm|PJ$rrp-D^%c;U_3~8YW`iu@U7M*_%*2QDeOPokRLAr zU?APP7#s!w?viB&yz#k7ReMsI=BN(F;0)J@6Sg1G(mzm%XSeQLJ@)_}T)shva*S=2 zCi6vuZ%939$=#1)5pkTIK6Tlgq#VVkpSuZMwOnjKk*=72zWngLcBT*0tbYLyGy_j(hVh-1RE_k+PVq9L7U3zLE3be4euJ8RuRp^1N_K#m(d z`_+mrmaP)Q3(%*Zsn5hCDzSZJ`V^(oQAEOdv0YQGJZBv>HYveYCt=|d#_-Cd)xOpq!}0b z>x@#n=n{=(Qr|XeXN$p2%z}o-Oe!9<&VM*=_*|cb%YzH61y!*qo}yFPafLp_W(6!7 z%K2nRNqo470#*=U2{8jNy%>F;4s)pE#L?dLkoiTIqi9ONMT_mkag?!5toDPdga3VE9Xyjonk|%Vx^38siY8cjJ1VI9bmIJ4JG{)_2Gd2bKiv zmKg6qtQ!Iu&g#8BvKwhCClW(9Ql`7J(YIghlTzlias3!Eqin9kg*C%!eOK8F7%=ZV6fSF934US6}eXt8Wi9>ljteuyqqMc z?$1GTU*wqW4}f*HsaWvDN0YJR)j3X$!6dr*+0-;^aImGjDmFOErgc$anHKxYwP(mtFLsi&t69 zoVd<4t5g(WCIwT(;k==2gRI+>Xa${Db+vo7gkP71L8nuz(=L#Eqiwc)6}s^!iAH6( zDAa0t6ccYoe>)E=u+Md=Olse7wXQfKkZnBLO0gLM!?LnBCse=!o^G22l-OoGVSM$b z-g9)Z{TxlPPP@0N@8zZR49ycc;}UA1kJXYgTXG%v;8~` z!-+J8a|O~u7IlO~41Yv2KEfGQgU#SGdJ;}475HRfd~n>L#A1FoGfnN})D#+t6pi9m zT(Cm~L_AGFv9=RB=`H(;aJ#wZb1(#g354~-8y6kcrNGYnsJKKDz?Z&Tyi<52xCekb z!Rl%{MMJf)Ffcf@Y*lST0T|V#FTL-|TL#@yfQd-k$|{?sREX-Czn*E<+Py=Q_3tr$ ztX`1yoyyPjAF&2O2P+QYYF_0CARiKi1&ERlvibY@tU|_Jzhj#e4xh};Oi9fs&6V!` z810TJ3jhokyWko~s21SbrK`PAFXF~G(O1{X#PppCqzIA`!oX_r1iH)Rg!Ut~_Teui zJkX@Jzh+kmdc54oiAj4eq)dnmU2}qIZ-?efLCJb-Tn5ddMIe+<`@Md`q{Z3yIrsVs zT#aj6gA2;kI!d@vR+=3OJ&fUo?D{{sGZ)=+yLdrIIa`R}vCr3pm@}1i(zawbNGJ_W zG5TK*B}U%^8F*oeoe|pU{?ZDDGI9x~*uRo^RifHN`)uUF`=8>*qqwhrHA_r9jcp-@ z?>8G4-sxvh%D>8S6FG@9bp^%BidV<;S95!-=co&$D}jAc*C`8&*tW08MOYU}$?eKL zIWpD|NVa0w=~BxJr}T&vH(2>H%0|@-)E-Tjeq+IPsP^mL=bKBUO8v);0%*d%H;R)M zYt*!5#&N{-nBAi4vF~1q{DDpgjn4sLq|Z^Z6mC~U!r0p7y?eSCx+l+?kX}B{uJYlm07w=;AfhF5_HOQ74 z)Fl$<<&S50^5}0Zj$6Sh)5MUDH@iXUCC4qm_<|zWX%4f)DwB!UEc2=)(B0{5@|k@$ zQDsvWYiGC#lWo`|uybB{gYcohdCr}x;<{-)xI!%`rItJZUH~Nr#KR7LP3B}Yt_nO8 z)9IAb3OdpErWApjhfXZ8-PsKRlmxm7FPvdvZnbrb1#C3_DtFr$^#_MjC#wAvh7;Qi z2tR04jue=mmqB8I7<#Z>D`_7`cq_J>PpeT_>TX;90P8;L`FnJNhBOSK&1Z?`@BI-^M|n8vzW=7@{|dm;&qYoMn*;)MN5Fk0YR62*)*P9Hg;_f{caX?s>S099`OR8!8X zD7rH9V}f!W83+-97x~;QR$n3C1Vb+gmAgT`9+Tt#M8w3%9li?Xt`ljqzG9MNF+DlU zn=T6O9Jw%mAXYLxLl-c3dpZ@#_#S0@xEmgR3GCPGroo#oyhpot>lY--juX!}93@}m z%lEj8T{J_4PwKmOdBVwe^$2XLu)6FA4jc2FZALKDZKWZRIy!UHJdmI|MPiL*mS5!7 z8doU5%9$J_YWF&yd>Mg7s;;GQhgcMCp4?G45KiXj>NI+>Ff$BZO;vCOS$#O5(T0YeQ#l$Mc2 zH>j)@nME90;e_1r(j|pvD}HOz=xmy?1w^c~tRLD=jIdKA1>YTX!)k0U!{XZ5{@XTF zN^c&t0`o+tJa5|wOm=TIpBpKzo8|I@oBW743#;lfh2xNN(45V}t$jXmf_E?-OW|xl ze1;?drxJkFtJ<4fl>kir-lF(ciz|^tb zN>-5~b+sb)-*o@N;Q(e|!PBUDcah9L+>OQH|BKQAFxGzlWAax51%mRUHl{*-8(~AEc$apCg{R(ln)osH@H|Jt z_H*6@X)|OZ1(GjB`eCM>3T{iv(Y`tgW1XY$ve2X;KA;ar@+lcS@1E>H6EQ|!cH=O%o zwVraH-Hmdcm7V0wHa#{DqJMS$gmTG*Z;}}F@HF0(Tw)U~9I_eJfO5iivKHNEWuOW< z3{6mw*L2sR>>^>giX*o`gu*W{M~or55rg63k#8T%Ro-6OF!;V92kA#TN?p*>4eg`d z_!O{GS?J$QUfE5+7WasIye>145|Vz^fw;t4MVec(02Y`aXwal1`V~sieN4{t)R_2! zgJFh_NI>)XgSB8do zSif_3=?0LWIj-M^bTo6Jmp5aDIrpPvEwr-1oP}YEJY^e51x{^%N}SDew-r+Nm3C}I z?2dd*0*plM{^Qv#1Rs*Fd@D3QN$6xU!;oKSzazkVxNYnU2o!u5P7re2XhY(+QffUeE?i>4fP%c+<7!Usl?Q7g@76u!X`x+6sb4kx$}08wHCiI}k~|wluiC*(9BvQ(iPbQJu%lpS?Wm)igU1^C71#1ygrgX*MG&_( zVtd&Ez~QK07rC>WTO&*!aSo%vip~~vXCMu1k0VB2cew#&>;$>!k-OrT+wqU$>o4*@ zjCNrujx5lP=C}c}U0t9TfH^|PLr?Vr$*IpEXeW?MlUA1^h%Zq*8gEHvwZzIzIJ)!A zsj@_c9lmxukqUU_%}5NW19K^Q17ua|46~zRGoIZC5*C5m-i zYwyl4`ghJ{DKX%`x6tUjt5SdWL+qiWaqZfYlUFbh-||!uh@BY5qU5wsU7-Hbp}3gn za-sM#j3uABfg~ygqwKi%xPa>f(=n-tq{(2R^wBQKT!+BfB*>)RB`q=zn>IBw{e*BT zPEhe)^YX_+bZ72-v9MZlGx=xur#o*{!Kzee*X0e5#Xm=nbzcP7dO(yo?Aq?3Iq^n5 zA#xjuvhE9mKEI7cjS=w162W6e8AgS}A>|zh4B}~H5#?!Y+5gp2Wq&m;hrh?bDvbG< zaf<5$l*0d?214JjCFm&3?s`7?-Z*jM`XLYOrciC|Ca_{XV?{#Hlqgwc-4iBrSeqtD z&G@S*FSWiBP9f?1F7bxPbMe$T5rzLn1P>pYN}m?zxy+G!kdbU7g~k%(d)%sKP2GAS zyij9s`%P%Saav+D_M~r42)C{|#D68oQ8rlTbR>I87xLd0a9S_(@%aJ`+(m*Tz7AVB zI4m5h#p~nxV+xpYIVT zm$_Fv?u$*aT5|BSu|J>Ug+4r^lA^-XbN+!oD|V7m2XHX<5HJB22S?V^V`LF{+gX(u zfF=~(W3WRIGJiUY{amA*iY9RxBhz|r6Kd^OG8S}UREiDN=)+*Ru>3OxLSvEZiEriF z$~>{0k`fbPaIZ82I}a!(`3km*a-$^0(AGEX_E6+?ZqGAQ3hei1%3P<~EYPh%dG-eV zep0Y5s5(ntFsTS-bxBo`n6O@|-?35%#AQVmmF`DrFIYBuAO^K~JgYkcx*c)V)d|)V zGcyX#mQu@|)`r|%Q28`pabN^9$hIZ?EY4SPXio)0Nc@188Wt9xIMOH?Bp><$?;Mi5 zKnlp06{fL9#Rmm<>zUMwuJJMQRodw5z&4(p{4n&n^~ZoT{HCfBlPtBxvgyZZ>#Qeq z>~L~!F~{e%s>)(f{^{h?iv}{1IE~@ zPy03(90;|&OTYc!Y;6rKQ4RO^jh(4tK7JpC&}1PF%$)W>hKo5*Y+Ee{sC?ppy0jfi zlyO^a4(ir5c|qVW^LqYm)Av#D87n8q%NORlD)hXy>%*`BM4L0OZLGiV-q^45{#rB^ zG$fL$c4j`uN&MBBS2Fr2ffXQ9P-3F;Ee44Ad>yqOvGrz0C=yHW3oXx9Zwx$o)vJYYx03vRu z#Wjrb9tM%MBgT@`0A^~>e=w7PZ7)u*^GZ>m)(rP|IE3c~wWM)`jnJEeDD@%?g z??Q>mm<8ytm1%y(qHQ>bqcE-@Q`@o3 zYi|g=OwiON&^^FJKB;i(HyVeVO3Rz;40(#8!bS^aDZ>|28}+Oz^)BiO?Gf2Bf*kk3 zrFwpclpnfY8KjfYln$V9&YV#lQ8hLEhdl~Ezwp0L;jn7i&oBJ%Rruel&`TNr`xVB6 z<=zIzQS6KVuy>@*Z4=SIqRAJ^;Fz`?!@$5$XbWLVnrRXk_>!*ewJWMfMk^D{ujgIb z^-6ZEE0zuZz)@Gb`>x%6`_6+h9=&~X^eya=v`6nkD^ec)3rGJ#mEE@8piom%{@)&k zw@;2fhV7>QqmQAoG#$MRhv;Q^`{d|nI6yxGSF{5A!i5T}`x!3DIB2W7yh|dk8uVT- zZGT)A-S3v?+$%9tqlgNkJ=bQOhVv{*FJL31K2sj*t>!3Lp3DhT^)}26s6--;mHVqV zSbT=2Sq0CRfGw$HEZn%a?4~<51m_p^q7G^^}nmz--$dV5J%!wYfpWgAtwQthH|To`BkrgcMHPmoXD~F4RYc|WUJnsSO#O;1ymVS^o;1=l^+ zTMj9_L+S`Sbx&iap->Mbb4|2-{0XJ?F=?D9BD-vAsesHqmb|m+YKL{3Cir-;(qq@Q zy9y)psH#s6EA=?0PoS^itoi)Ynouu79MmV+4WN#LeSrFtrwyR~*0ppCGqso7*GUVi#>)xj--~U($>mS1RZS z#UIjSF@FFAXE<-4yhFQ0)klQgCOD>lo?JJ$34#UP1pNd5B3@K2Ywn~5#`F*QWuqG* z4h-E1`#}54Mwc;Sz~lA+g9f4x@b8K2Up7)a5&C_g{VR$isRz9TpWwT2eU;G)u;23t zmu^w3w!uFZCbL~hIgcae?or-*oy@$Z6eoYH-b>F|m<(p%VmaeTt5l~IUddbO{IZHE zdB|q`i=^rWh41llA7AHo;`xF{;ZP4<%aGC1weWtJ9!;BZgX&XN-{_Z8n5v9W4=_{b zAZ*l8^{swJZC6xkVULz*01qd6UFg{;O2+R8wxtHKianvp)SFjy5$3aygFKJ4l*!O~ zss2)7L=My>9%}>xgNOy1LPz(#-avpMIdtz)X;a@)@K zPDuH)T8{Aj2-9~+(SZ!Pu9qnZ*OduW=26&hlsH5Zhf)kzn^I&I48RDVlFOE7GENth zILCrx7&G(nlEJ+EuUzrqLAh*#OAm?kGz$vV4XiqL&pJ~T8C>WAV~TuMBYC@HadW0x zZ}iabBP}P2i^-~pR@a9C#|CC)o{J2{N#@dXf=8EBuYWP(+=FL~e}) zt6R|*hh4m@D&zP@-Tk6cvX*s*YeiAa6I)Vs$M@cD^$furkHkJPXBdWbTSY3Ju}LBh z!1g){GcyoPn$N8THYujx*R+6lWiX`fh0zn&m{l377m;dtoXue0L`i1yggDt+Ix$6bzABMy?yea z*=;_Ze?gG}+I;W4%w4H;ji{Z&V~D<9ayqLzHdO>gPfyC?Dt1Zwj^CqT`sN~RyyLtD z+4~Rrz??0S6g`)wNm{EhStqPOaq^nShcZ=$|0G98-UpEPz*BwIfwX+D%ql+8w3zL1YAbREsnbN|cVWnAW_*tZQ^) zjnoL%);P=DI#}k)Wb1(jV2kw(N-&8D!T^y><-2WD&6+JW4m!;A@kQ*pMjz4d;p}%c z18O#M4e%V+AVJr@WQy{{wYxyB^_O{*X+zaj^(24ZlN&AJwdJUgXbU}^hU1XJhWz=Y z!81W>g*ABe+IbdYJyS?0nb!7*_U0i#PW9imOn?~cB+FH1&R0W=*aADp-Kiyfq0pw~ zPxqPZse~+WPHNai!wt7`D4}PUEP+sVjk8(+eS8?u;A^#t6 zYpfP%D3^AZaYFD!dNLy*Tpc-oA+e!5hzI+lAnC!mtX#Tbv|TIf&~GE4GL%KVjexF8b_a zP8l;DfL=k?7<93%QVv|lf>uvSMJNKr6zGC^btpi`AZKn(UQhYNfoOtC=WbQ}e$grH zjMZ0iq>KxAz}0cd4{a0^MNB*nPVr<)=y<+M(uwiIbHqC=wx0DSB8~#R)2p>uD^R#2 z8`f2^1ez_@LRP9cVPYh)Jv|y5qATpzU+Hn1R^6{JfkiIV(vQHr)H zMXJHeKB0i9s$l=9BY;d!LV}hJBZ!5iY+i_Qb$+z15KC@#<;U_pv6EvEaSTyn%YX}` zr1NjIEYxNDO77b@A)065coC_z^a>CmW^J8j7FEG@q2V%bfr>CnVfGGZe8(Kre^I@< z&{qd|f{})AXhPnjpz%LYOlFaEFc+B(^vR@;k?XDF!zJusb7D-LvnYni3}~qPYdH<33%d1WL!v2=_Mp|| zRv|2h9tDahD%?@0?XLuYe zRwdCRQ8y9Yu5Nqx}fxTI5Vz-+{cZkTm!R$G8Sewp#}sTA-ClS%MTJnzXD0lrm&#! zCGQiZ4WP%x9K}x{m8|*7=LmTfn>(FSF)foZR93hAvRs-gndYgO*l3HGK+JcN`*7b!--?wuYHX7r>Xuv1W@VKz*X$wGrZNHv4U z#0iT|AUI592@N>PNWxGYACw42Ie#nYn8cmq@)#xVYK)*47Sw17xM}YWuhQiYI->{E zqm50IC@$GHO~CUtTcuF6Y${`K^jwn~CRFirc}XEN5X+jR83t`XGiU^r;{yp0QPWW4yF>*tRv04t#2x3t96H0R*hot5FdE3OI!Q%H zcsJlWZq+I+t>|N(3RDd6vXSXsPTKq!-`e3|CFuk%e99&W=~D1WAkdNoP7^Rje&uD6 zSXHjGwi2y(dVSW5gGHQta)uoRVebWj{CH(SpucG&2%mp?6okVO1gX5VRurxq9}4(D zX?`yF>a7c;l0fEDHu5_Su~rw*qYOQa3~e}0t{a~xC_~MUl%otCmJD$LwLMZ!jskRu z0<=d;%~603On~<5akN={{t0LQG>Dcvip+zE%t4$uN0HeVkwJZU&z@UHY3NlN_Uz$w zl!o4D-tRZ>DIVWveQ^f-q=g(%82wQU_FD`jU>ri`d|80_xkgNvkcK1M zcgpsAL+V^dZ};Oy&i1A?^o`Wfx7+Fj;Xje{q!F|=xJ6%7b3=`VbOM^zGwn(MS3GmX&LM#8)42gcS%VS3dvSrA*ygO3h)va9bk+#cpX);UJ(lji7gqYhxce5!TLQTethL4Y zLXF?6Sqq7t(*!#fYKFS1TvKoQlWCHi4Cp_@kxEYn6=T)A2Ob2O;jbghOy>T?nIUc< z(G2)*h5EUkV;P5dylgJl6FbLlMccw&wbun4G@NQJYRD}|WOL?1X!^S;FDO%^3tn)} z$4y@>VMJ;(<_y06+hxHs5{^H@u9*JPp%z3T2JnxPzxv_YuUftDf@gOyPj4JUB--)| z5vazk0-s(22^ikfJToS^4QDC6{U{r07(7oXe_~n7aj4fzL4PWR{AZ)Fx@aQz?ZR zrHdG|SPM`7MLcGJ!fc5*pPvnDg40v{$%7U%-L; zv9IwYX6$==5i`8?AH)oHoA+=q<)P!)ru`WL`ZCi{znLBa3hnN1L;rplrqa zTF@Sb8d=(1R0g5lYa^yP9{9a+kdLH|GV(^nZA|P|P;OEcw=}iaLg00*lPMGij+(=s z;1o9#m}7@v@BKrm05SX(zJ>LqrJ$rT&93Dn2fy9rZK2=oEuI5k!%>!aEG$BqT4=f$zq`~fdo#q)k$6N1`?8kc(`gnj=|w+0XgJ{s08G&AEpkF zLw}emKo0$(X#hFgho%7JaPRZ|@89%!YR+{`u{ZNn!*djVY-OoktWI_Vsz6(#?L{XD zRTO?od!QZ_T+G(kg05j^yD(xU@L7zldqC>o0>9L{yCAfC6(1sbd#@F8qg0o=6X;*o zg?_J{ShVJ0c(Mr8Lvd%V1(x~WLKNuFJqQD>TSpvdK#u}J>o*Vy8n;`ac%??Vg-0cV z;q9C$jYNW=t|1WwW`6=f;MSK1f_k^&(9W&d+M`)t7;1#wo=wTNPaYi+0&M*u5oBU< zz+Z>-?Fe#s`L9(xaU)BOp6xuYnP(Cc6R&=|cyaUM{QBns|L@N)E-#<`@FGZ3{__uS zUSD5yp%m078|)#VT%9`>2+-pl3&1wGV*%zJ-?0d1JB15jeqg8LM#yV;9bdY32edyh zqJbT4vKK;P2!SK~pueWQW&g&XlS~jMZ+r8>@Ph%j+u}|or++R~L`4T+j+KtO-+%Pc zX%s>?4l_>XrCt~5BBJ<0F(pz=Vmxupf*yrKJ%ry?KH|`&SeaGA9xt^*;l>GvrwAexup5+EH+VwtK!Jy7w@;Y7(Z2pFy zq>%wr3KgQ6U&6d$dEOCs;(;kovJ{B{znxGKo0Ia_QU|QKzL1lar@x`@m5)%H2ISS8 zH?4}7*zfMcbwDh$5>nsWu?#xp%<-4OH(v)&o_>K>uY6Rc?$8795_Wwhc6vL%B!N9{ z|4PtrI0Aemc6<&{Bq%1xwn(YrP|y%2dC@#@XVnZjODScrCOMvZx_G9KOA?y5j2e{cDG-9a+Wrkzy*@{Rk-ARr|TauLmy99guKSn^{30%=S~f^I{=&i3o}Gy;KC`F=o-rV)ti$$alTVL zOnIb8=8|f^vetn1m;BWShF0}wlrEk8Y#pw?cf$+@fTp|{OUX7@jt>3;*95rnD1d;L ztn?lZsYC1-zKXtA-6Z_iXBcemtvoAkZKi3@FV3w{uiw@Jd=D?qy$Cg{4>tY#69!(j za8Ga+sW{2it{oLV76f{QVG- zDK_5Dm83^njo%5dmh3!(wE2dAa8n@IcfqOKf{RmPgL17e~x z6-FTV-W@~N_#NP4Pd*|_iq!UrBD(Wf#XwJK7td8zu^Q}Y1}vMqGMz3N9;rvY=7Ggj zv*)fLUZm!iP%jD*5W^&c01!thNfxtrY$``UssDBe>@Dv9q)0p0tDg$`V$WkKGNfXZ zld%HCa#Ob9@}wV>jujn6R4LbcNHF|JIu(<1fErbY8Hu2<(n^OvV-eT;rI8NVr-cn@ zWQU-BAUiu!v%xA#O8^3vpDe9}_!HY1*&p%t)wAzjyt;XPadr0k{MoCw2vk3slXt7s zaf17Mv`2S%MGQ9TQa&QBJmj^5!Me*oquFsQQk245DMh`Uzj1rb$}7 zJznEogP-2%Fy-%HL&EB?=^_}fOcL*+EX%!^a}TbHh@Zp3@_RV@UAknk*Wz5ys7S5N zV#pNuB%eHHt0jDJZ8W?6FVD`eKK~Ss%z_(GCRnYBf_}|txevtoa`(!cnm7v z5c`G!1t1Q$YFyRs_YUy5Pwip{N&6W5&YTx7>jJyiA@>CEVT9ZhsD~1A|1Wvh-rP71 z#J`HUKj4mO!*duO157Cg-0`^1wKojIFc~FLTXU|Ju^dWZ`0nhk){d=uH^h4!>V`;9F}F|o{JgO|4^%E;FF!L$$0X2y#Po2oZUu(Sn(?vILaQy z!73Txz#et+Eo7k20$gq$H&)@wB;DsX7uWL04qs^thvQ)0P9)yHvvWUw=r5iL2)>(b zVFc)d-Nj6>PIeYIX#PfR-=N_5o9~B{ba!g6kr%Pf;gT&kK_gpDq5&iF`Xw@wD(ZDa zdIi$W-=nKAu>^0_GK)nnleG&*CC0cOI5`3;L>KA~#Hg1mmDU!^NyIVLU}?=spe-A& z7E2or9%@aNHatAs+AM9jc(^rMT5@sh`taatwzR=NTJ4sd`vp8h_Rt{IfaX*{c8~NS zK|A#r@gG%}&;s<4bl5E59!;A~3;5Wofmq^pqE+fI8Q*bm=c(7^Uk-OUUz$jE@E zgRmb}Z8t)EB*onb>(NwqYexGlU9R$O^_yZO(Y-It9%4b@+thNx?^8USTIKj7fM%~d zrL{^;#aS8)M_?j)B(zVkF?hz-m4L|c6^E{8@){*m9iTVa9^(e;w0r1$opKXBL`kPD znzbAFCiPG04`E-l2kvvq zzq`aBUu@aBKYo+QH`N8DPK@j!^c6-zSC|D}SY6Z2+%+d7MurE>qf7F5nMnS;SPA+F zjogDl(CSbgtEyd}oe}jrl!*;WUgu?CO~-?g%zDrmO@zkN7{kc!iP)wwhKHKQ@aN-e zOel|ajWHZN2#pD4Vw1)&F9T={bS}2l2(Lp2JOA1i%B!Om! z%#)|pRe3u29=8P8=y3?-W*zpCA8v13RRq|J%j_IwIPK(vBJc`{O-UmT>yz5TMR>d) zM!jV!sh6|7&p?-CX0)BSaoTM;o^0uiFLLvk(R@yl=b~QKhu=ctxmy(;KViRQ&9!ka zk(j0;47pmKCXgnWl{LK?>nEKZ3VVvranJc@YW6n4S4>y9+?6cXPGuR^aE0ODY`5xc z3}&{zWl4LAmF)Fdx_~LU?P$IV>77a-t} z^rgZ`pr)82z^2NczxKbsb@9hPnmiDX9(omxROy}kSE*Z{4>wlZ;azvRODFb|=>_x5rgj?Q4 z>ef|5o0oPmM^>~0=ws58&DQ5u;A4@zz6LN64+gnV$j?ETk~jyvt2B=X=``S3s5X*Q zvP~f}Kdey-Wun0x1@N*L6Tx-}|Gk5@l;5ZhfwPK5bpM@FA@7;cvh18=f?VGce$8)B@SY0b{Sjl8vN{=8blan# zbCFXmtpsq$-4uO{J|S9m;Ed~*x}lex-SSbl7&mG(ANp>%8?D8S8q|M&KBt{| zJU5ZFU0hi6`Sixnni}WKP%f+*55Xzam!|X_!;T8rsN~Lm#Hn#dB_h39!MuDKMUVJ} zkL)8A!XlG&O+~eAuYq)~$mhKjSsu?&Nn=F5i zt!n_I$A!L%#Ukd)vCCw26Q{b`^(OkZ%KN>{$ooZQ0HW7%O3}sqXMQcxw3Yvw^2kL7 z&vMB(jnChhsa*0@R#5D~#KU=SiWQr3(OimmFZ+_(Z_bqxPpChcDc^R(9XI(Of;TXMl#ZTZVa7=k{ktK zA5N0m@DSj|8d{nz*1gHnay_0TU93arpd?2-aSta&;rKTf9$$|nLAT5PMCf)oq72C`I8MG>FkoM)u+$SdP9f_HP}s3+*1TTZUn<)L6{HB|9`Z9?ZSAL;GbV zpO3bNxNlYF5TA?eM&{^}$g$ov9?-eJhXmIIe&1E$P8HYD_Gr==p@(`+cUa|%-jhgC zgA(>;P&2VaQjsKZsVmr9e^z`QpZCdv80oy+4G8gxB>syq;BS^q<7`ickGTt&rMg1f z$vJp&lA0O^;N7IY4tA$fB*991K7UFvA7`0NMF+zVn`uderUEGqWb{4sp>Zze5zQ@m zXygrM%gwS}Kn_piPUpF+jab4_uHqvw$Ln0V6Tgd1QyF%WA6jn$ho_=D_1PSLAq+&` ztVMMOhFJh#%zmF!(Az~Ouj4N5V}X!~J(@0&)IpobZo(hhK-N0$0kxb{8;v=~MH%qy zE{XAXS{F?)lt_~DBOcMZ3e|l66XU=!U8xFh&Cm)KI$~7~t55L&{bVaD7K(j?j@4N> zWJlQ&c6}?dCFad*@TzyX5StUBY08uax)$@{hhC1^?<4%Wa(q_EzedG!w@HJ?5rlGA z(TDnM41d8B3cXn!>KqJn*>iaxU*}zy8;wK;U1`E7PZWS+Q_!1Ls{ElAV%~Vp^1#%=V z_fXAU6cC=T_(GVkqSpkS-w|sTs5sTR6#nJGw$~SL99r2!Cec%LCv0P_c_ENDC^#b@ za;XDvP%qm6NIsus?4E(1w6oyVs;N(xb+(0?+Gs#eQ$4CyZ6B1T zh7Wy7V?(57P}L3RqCtfNnAwYqU|oK>nyov>BxgWm*r;TJ-6}45yS^ImG$Y7NPm3w{ zmhZfrBBZfgK_MeuS5HJdT8wW94r@-h@1Ive@$GKiE;1yVKlOV zjX=%3BIU?5)qzr(Ecsb-%J)p)!h)J}b(2D_MufKolj>>HXz@bLSGIk%8x)54DAJrl zCT6OiUL9AVqtjc5tP;^fcgCvXcbQE;szs>T{kC=iG#4paKF+=2ZHZn=Y+#mg>~H*6 zFVhpOgLU>MmrEHOOu|gMhz()`86&|4Gk$_0#jy>?I2oC_bNJt7{8#8C%6vZdbo>zK z@+Br!1{dIQlLF6k^f{-K0x|LmA0%IME0+d6)t=Wm0IBehL9+IaCQrWVKoe z<`TzqEJ%4m*~QoL9;Z}_e3eN}1yv}!T4iiqVu~rMa9ZPA+Qos&QO|5O78ort$IJzx zIXO<(QseBi-zXLRUHfZP>~J^8Tl6_i4O7Xd{zmzA3&Kzc=6Xo{`=wdQ7sjap-P%?!Xn>VBh zImg0WB_wxoBD2FMx0p#QA3s8DO4B(c$Rr-@NMca?r;=8jG#pPt7}|@IHVf8I>M{qD zB(hSa(X;s+zSJezJylc9WTy*DcPfbRA@ko`a2L4i_&U}uD$%9n74uiHiSePXTGXSc zV3nHzqrvd$&Q*F1wx8>13Ns>>DsW2dPTZPzCq>l5J=ub%WZ7y*O*I6>S*Yi?cR1<5=XZk1D62dZZJ}r)i$8_t)Gz zv7AaIF__{On1hd=Ka+HL`onu^vC7pQNcmhON%>L$n2Lxga|U2$eX{r^O+4>7t-)5X z^j&ux^GUs#`+RUcv{afHtb3Kcu9bz3VzNEXP>R|SHAKdL zdU5si)97neT!|q~dr_8_OWNp3bY@CgvlqzdhF$~eKPyx@!je)5m>Ta|O%BgY0?S^l zhS}O3ZSA?%r%DPl(qWe^SBu5W%Gwxf*-pHhRx$^BsDgjqPTkYyhwYnIfg0YC5T}5!IpfD=(GWN07FO$Y=89K|MSOh?Gm_Rq-?@;O z=Vu_s(P;{AD7ECcN832D7pAtzjz`i;#Y}>G7+nhWsD`!7-D=`)C)HA>kp|!BTvkyg zQUDvLr|{=2TZ5lNz6EO!ZJ`uAK2KH)iCE(l4;(9We-~wn-snN{!lx6{U-EX1@8(0a zyd#i)s!P6Cle_sr+uM0CF$$y0u^;0w4teCSfek+Fqaqu0tQmZ-U6kHO9^6i8nZZpa zZSvTUmMi|EPgT%GkGm79X}3|c`xq_rOTiK-Qv0UrJ;!|(;~AYdl{d6+#OZgX{H4)h zb6)^I;N_agGO?!ErWCDFy;+DTI&CB}y~%G+7cxNx@g^ZrGbq)Vnl07`CuSqY6|-pT zM|j}JS}y>RXcHJ^T#n|-mIv7&8K&m9ZwpW=TDcbx@Zntxb!&h?_i-v9-UB)mJfP2Y zw`KizJ>a@-zy^B}&>|RoY!Pf2pLFfLF6j)8D(GVW_#np<;!|Z#4RyB!FJ)#bp^|zL zk&ix%X0&|f@+K1rX*y(O6oEt)vX9|=AANWdt@vMU{xwg~2mI3$c=wq>VXhvS#pjpP z%d3~qe)_h0B-74jk>Mz@&4s@Cj>BlVjuNGbcXVyV8X2tDAt&Q{i>*4im{+`FpwezB=uXQX}*tyMD#A5*rYoK#IP6_A|V!D2LdhQc?*(Yb1*pX-)8w%_$QTejzV zzdhUUdbmy758|&5{@z6VbwF2d6==AV*A$ecOAVg&ne~kV<~UhH^;o1>)Pymn)zyzV zg&AnH&U%8;J#^u!O`OU-cU~|J$jUzDI0fCpqZq%Mwp}%^R_Y#l%d~a_wdVZjROJpi zx)cj97@g_OQH-~34UtR6==iVTJ=Z*6Auvar*ub3{jaa60zNOwBeT0ni_=)H?29s3x zp$ZJ*$|U(V*_X;1%17Q>;aadPc&mj1R)keXnYDDt3RT{ZmcMMG z(Ddr&M(W&5s2>g^R#3t>!_#pLBz41bWwx$9QY7qTFV^U8H34U3i#r3?{A($f@I-~A z0`#|1&~ncA5vi0Weby}nQQX4(7rk^Mf&DC)%he2a>a>l>t~q~6q+UXVTGZV80H^49 zh21|)@ES}G7DaZAI^e2fmEjEIAqOQt1Ab1mxR&|4dH3UB#AT#hgW0k28Py-o8H0T@ zlCCezICvEKVA~Bd6jHVMDnlnrvZifHBB@P?N1YThPFEGMI1d^05Q#GkECYXrhVve) z%;q`q1Ki@B7Y)?Qg5P7K-DqbPr`1U@0;pHBQ`U6UetL~Qp;17&e5Rinn}o60(6~(1 zEmwt6LX}CFW7ZYWf|TzGe9J-+jd!so1@JL%jMYpf4j344+h$f3J*V1+!d#l=`!0|o-e(1!YV{L zhR_tz)@ba}<+?&`E>9WYu9PY-Pj1sv;sZ4Akue$Bw@u^Fw;5oZ>k3E{kN7tA`gz-@ zyX6_*B3qNLG8_*?SeA`iK%`8Oxt%M_8PR_K-S^)+F*44U3Ue8_SSdB+t*Bzei+Y% zdF7lmhqD51;~BeURaUGFBCT9ra18(9o>e7b9F+@1-mH8+1H$A-61w4I6pP?fy47v9 zfd=X(MgkhLr*!g7MdBj&X>pqrF;pwvOF%|A8z9ffNefBFF&g3K89@MK6Qi7V`5;!u(wSL~DB> z>Q`EN*Jv=r~YX!Spg)!HmNmFo1V&C+N@6;X6<;T(=(#0K92e=x`sf@dN@sHV*`1?(Be&KxBCT z1CXLO59xlu_w}*}22aYvcRnE6WAZ&9-v7W31KIdrY%nli@aQto3*g;z(9z_Ol8lsw zZr?v>Cc1s=0LkdZTpdw5dI9;U64DFM|AkDx5MBZm{ehcc)Asb}46uRS-TZ2zGm`B! zFCWzKnpX~Bb))wXzRbsfd=G8qnEn&)N$V}V~@oY#^eTyD*` zPp@!go<-OER*xoQ<4)$ANB#N#)dLL$wMT6ku+n{18du~sDp_+vkGo=>~T*h?7gxzfi}0# zSv(G#uh&Ayw0e=D(KY zkDROJ`bs^1^2BWJDH+O0Ov5btlEW7I?%-PAfMf#A$U2nSfR}bFve6pvvjxgByfH)n zXb0%AB{apISvNK=IqYSq_+XH1^r{pFcdk8AT99bFsoim)b7kDX@_BfyC0!B z=gnogJ>@nKDlOisZN=}I#2t4Za@%?U;S3QvhLs~keeMrl-l2g3bB+jQVe>J<=j3pO zADURWP@0mWo~3z5Wn40)DZFG1bp&ZDG1FF@%IHTHs9-KONR-da2r~7Pyb=A#R0@g&Z(2XqhB9gEA{Ba6ukZI1b&~1Y%&vn!Dj%{d~{d(O7u?& zsZSC~O&;^}PbTnGFAcd`TS;Fa><`oZ?Ii-4!e}3`eQ5wAU^p!=Eo^21{@{%U|7Gu3 zo7|>>f5mfrXac#EH#59uj#A*5mUh|$J}^8KN4YcgS;4Yf0>gi2ceR!*+ezfaNe-qA z1MQu)+Fh+yyQ|f1012cJw-eE!H+@m39#q&Wwua(r`5wO7E4{Gq99FASvghn_>%kA;PK{OYGhWRYp|RwT7%z#!Ol4t!Mb&gyq?^&M!v@*E4?&&XS}`AYHK;pqYJxM zT-$U(wL_Dny926vj+RR6WCkYb35Jw%e~pTmaJtlNUD}3`-ao@iTjxauFovzTTopu0)UI)iNn*@qCRGn z-9B{b9{ix*V8JWG{RPP4vK(Ez0PLAt#jck*X8jOKajvv>EL)}mpGI(7ex-}H>Y70Z zfKpdWh436d=4ZSx;u;nMJ1C(&D2bSvw9{-{R6KYb(K=R3IWg^D)WRHcw1QpC*|1se zX;NgiHnVBlC$K0ji!$sN_L%uwBa>}hSw`z*OL=CBPkSn*4W{RE`J|0cbPkTR5w1(PGi&lFu5gZn?B^THOZ+^ zdJ|jD&j)0bmdsg~ELwsP=F~wO*r};C6Nly0qBdoWGj_-yrC#N88@%JLW`k7e?cwhX z7ku>L4iILl}--4R$Xg*5^=E3fZ%_Pw*{AgLQMqB4l@`i_PR&>;> zu!6hUQhHeH4aVYP-$J9+6~ThY6fNYJ4{POuM<5YCkc=v(*oJKe?c`E==Ac@IY{uI?|``z^|xZQEQ857KAR`>k#dS!;}; zxjpT>8>XeL*?_~NJGwiIta}9VuY=xqwmXP8aC`4(cjnPM0VChn38%E$-9)Aeqrevs zmta~+Y()XX<{i5s6}qUl*k+M!$t#PxZ$bM`pl2(Ma6{r3&MfjFvPxn9kD;0FWz`Gc z+ay-0%Ep77Uwdf&=S#6i#7Zy4@uF32%!4z%$(AOumYk`HJxXMxkd`vHPU6QP&3GiF zpz$aCXIQ85Hftm~%WO^`Ip=;->#QL(;34P6?iacSbUeYK40GDL(ZjL1ZH1X+g>uFt zaT!@}8(PMzscUy);QJ7Tor+gZ6L`pPRp;g<$N71!1I|j7#%_EiGUJTT8$0bC{3&@l zGs-HD=81-5X2r&-KqovucHp%k7muVsWBGx)#U4+C!U}^CTk$?I3f{Hf}TVGMU30aQjOT z{TDLl*D7G{joXnvvQdCz6j5T=p27~6tCMO)P*w}6K?AcuXRx>h$e4c7fXOUyu-jGv zt{Z7f5=~_r408-V*R2Mc-^o|RVWffkcw3JVkzba@7Egoh_f}YTt@(zB%zN+J@IKkg ztZBSm2_H0ZUHdI2P;8kHzahIc6iv1=Auj`lz4u8tDt~pNeUZ^>(86pP5IWUuH-~!7 z4lp)w&Ln!`N90FrNApY8E_Sbge!!5@H9ueDSfiDFJo$2wr0{3EGdkchrcnjVI#NiK zIX7mh$X*y_!CHhHRnso%fJyPQ0M4%`$*HmE-Dyv;A^^bD4>||0F?|cEPc7Ysjd$>Zx|>Mh%*;??y0bvqG##$k?q*`HP?HQ|h?7pb3zj&D8c`Lp zJf5sMGVYkL1(VYyZH}rtAa1;Es`FugscV|(!${x8tA?+u+@+q`RVIixlbQ|h)ZC@q zBuhA4idRx*jgGVCzOK;Cq$>jJ2W!E_YN1u{!7Q{^aUyI=ugdrxtew#VTF>rsRRj2L z+{E8x79%Cf)o>5wggQsT@g7*Q|7_ zO4}dqccY{wT9m|5IfFh_zQg7Lu(@h0dia_#mMz2IW*H$9z1re34I`k&f5O72&Hk7+2gK~=e8bX5iU3G&W+-U9bxXLinjYBEAyza3XW z#Z(tMd_9x^{=jxa7WH{Df{S|aw;}}WZ#YTFx#V+uFMWtL^lli z-L@1U9=xGw4|&kmZzzU{whT?ee|P1F$QxS z*h><5YO;Ul7Mz~&wOw_ufR&ibjAj*SQmhUxN>kKKFAOHQ3LdoPn0wmzq|u0K17f9aO6x6`DR%Q` zfuq%Q0T>S=jfXX*`&N~4dm8*9;ltRzjWH(rHM_#?FQ(%rlb9ceT6cJA87kM$Ec^Xu z_NaA>RWzbKII*ctttXnD_HXDN;I0JW73$5&88I zir6(NN>UlTP0?LwZxG=HYqsvnLDBz`ChikGm;7Ez|wjcxbX zdnuAs%u-3)+-F)y{?<0-<-gN(DP|NMZp=Pk0cZKwsSx}6A~0gUqu8VS`J+S^ zki$X-^5{85IHs3)r8^Fkvu6^Yeb}s900+CCLYzMLJKvvBzHa6v2v1P{M8*fXpMfTw zy;Wu}GW9A$p`|BI?HLJ|2_Jq&vI}KXXZbai6nWeXwq3dE(9P1+e3BBh0NLKUc!5S# z|K0!8*d4qMBI`K%F|VMDTeE8be|QJ8d5>yvw5Wc7 zX~v;~&UD-4>i;U`;KKD-ZAhYF7yUoI+(2~i#Ri&(T577#(5x;6r@BsFvQq=2QFF#O z06#8d-Zf>SxqlI(RprhWcFO7aH0%vc|M7qPU|m*rE1f#}4$ggJG`jounKbFWQ}fRI z+)JfynMXE-+@?NfCT-P~4dcYRY4oTwt(LIz6L_Q1+5P)xk+u|Ko zCpceb>+(>h{Oi>jbafgzK>IIJ_Z~7UO z-YXZrSXb;3P;&4_X?&Etko4Y3y63IihYcVaffo2vr9vC%aIS|bl~XRG0^L(xuh}8e zwBdZar@=|)6)qYqoh8ssL^>f>lFgs5Zf7d}?YDQ>DdY;hp~mY)MlGu83PsFE7yr}yc1ROe9nQiAyfE~&I``vP7GSyj z^nNESb_@|2MuI5xsiu8JxcZ(|J@Qgm0JhqJ{F9vOoE{z0W71q@*8~S51~l;@A_gQ1 z7xVd3ctI$xr7s7Q4IunC(4i6oGg0|3nvFQ_SiyT}ictXf$!ulQX^1i(o=CCo%gS(% z9tsOmD7ejxDoMOrA1^>+od|ib7=|f3;mM2Kfn&3 z(;@t@0&rH_zrFy;W>QzyL>E)@EGCCq3&vT}f{?-*cu{_kd3DV!igxUtlo+}-hzD2O zN{Z@i(>^Q;(5A8|Op!dulqxi8KrY`Bt6Xx4JX=SHJb9xzg&7ed?k#OTuZ4qHVIOKm zzDhU);fs~YLD;k)kIfa212Ne#;)*KY#Y0<14I#oZ%0F`~S$p=-N(wx2W)k1BXM=OIc=2Qfw6TDA0{bI8h(43IFmvKJv}SE}gMP0MbW}Zs6j*B#o))|3 zxr{a2`EL5G!ubV2#ooqpF0*);m{Fg_d_>-gIatDNy&aAioJfNu?OipXF-P_kKRJ0x z>+8%j?@qD1cs+ZDi-!F^GN*}sn0jw|Z#*#`mhir8>%}s&znn%7-g*n7B`mDNlK2wjTA4FbVYA7Z=vO=g8jZoLLGKEd}U5y-c)GMQ7?-GbBcK5a{+T_+H@$?dJ z!2ka3x3~Y9gwNFEJ&vD1u;iamCCDSSv(OCBszN<@`kd3ArCV%_Bc`S_&W)s=7NnJ! z`5G{6z2K%mT7t{U;j}?gZUP0=H*flM(!C=0*>6Yd1-( z$sl%ZU`)A#6F6c9OJbe49*IeyMb~6j)sj_Yo~zsx=F8>$Xo*TqQr&Oq&p||9L^maz z9Oo$iqPET;;@%MsM;kOeNOQ=#??c9eN6%+hN;Kxk1_n)2MYT5&@PJRSIWYLI9m1wo`;WT25~*Cuol zacZOW;AxC!nt02-KV5wkFoq$$ILuDDoB*X6W+BI%AYwqp-CDRWv@K5W0i(DI4`nfD zW#eKZ4PJ6gL=-%%GX*r4rqmRTp)KZY=tD>Cq%qbDcwS!=pwXiC@n&#e< ztA`&)7f3Y@d?~Hb7jxZB^p~C0XB`U06Q>>~O>(Ej#ypJXFx%Yi?=1j%*(VUA2#!y{ z%(f0GZ*3BHUX`x59(Rd1&$wXdF?f{oTu0;5R*#5IoW1=^UVL}z*rXjkicaHo5^;CL z^(0&Z{ZGTf*IsCy8;AErX@z!kNY^~uY@6ddn`Q)c z5Bscb!_prQYoiUztKR19zC5dJ+9Pvqqrqi~H@CPw?i4Sg*bbrm41CoKW>B>~_+GU} z3vEufRgI-PZyLzFVFw`mX-~qT2RJsc%PW!Sp<4NLy{{$u_Am)#h?TU#*u)Ow$qOa@~?aE_7kL}>SR0Gg2u z%V@W#9Llgt{4iJOPkYc-yM60%-3a@}r7+*CC$D+6k}wkQ+pv_{=h{d5ttnxUT1F`t zj`Vbk`^^jO_53{{gPvqkEdn`I_XZV?^Kz(d&EEAK%2Z*SdkO?`1Yfa9`ZFoggOYE^ zy@&E}mcwLc=Ho7|$OL_)b^}ue)Z~~0j5_Bz-AS-zHa1{3?iKlr$G*)USxhF z^izr(#GzC|$|x1ZvsEPPyHA(PrOL7N9s`|J+l*Y5IDv>RU&zkQ(}$$sjO=bVgtWc^ zJ~juR1@kfy5uksc3PVPQ1@yGCaY>(-a>6Q5iv>?8h6j|94dyHGLs#&sOntv5)E4Wo~sH#x1Y^!6tm_2m1_*Hr=k=2Gst+YuyMeHsf_+>#23i79 zC$P{mMc=~%JX_IIa}r#US4L-puU539i>H@>q`M?S{=yhth%Bbw!Q9>V?1qf?Gs`kM z(lTWQs@{RN-DjvFpB$_vQb*cGEE3^T^GndPYj!Bn2;@w-(&pyG=7b4a4z0Es6 z4Y}~>G9R8?gn9?b1$i8nQqbaejz}zwH1vut3FhSP3UXgxV>{gvAyR@n(dEUh?+oGe z_a1S1XQmrM*cu5o&<}w9&iP^W>fEh%g~Ns#dmXq?WN`_oT&W%hZ0Lc?uytpf3@fTC zlM{1)M=^&iI*Z{~8JbsT9rt=zVKKfj=?7R;KxEq82J$`aY~}HL%5OKo0%aD_%&qv< zZK=@|b9Y?}ueJ%GS!FjlC$6Uu`7v0)048aKtpPXoJuE_mMc7M~tX-R;_O9_2L&;h1G#T41{Q+_`LIj$h}hT;4qj=}ei+-XvB>Q5QvgtQg;L zh?It26dfzCbFky2m*U+uos;0aPUXDoshqS-p{a>MDTxGek90&Yg_C6duz85Xv8Pw& z=DuvIoQ6Bfs0Uba3Yr|e2&C$fskm$Ui{RMv6b4g*mJ4*iHY^57A=n|itL6WdJamGr>4 zrTI8SI-uIy=yW|_Wrg^&2f~^Lki#|bd#10p<7s{sD#hkw#`u^BzSjrA_l}F;_teuh z^k$Ljv(W&1DK#9rS04vAxCun}OPc`a31_{LFlEJ3S$VHae5==Vt>}7`XxF1w&Z$SM z>)nBfx*(#9jwgC;KM0#dRkZ+z8QfKpFn|7TpbMSH;asNMzOs;j*4Dl!?KT@b)m`Hm ziDbX>u4p&TC$92}@*N?E-bBhhe2$nq?s4u*X__9(rx40X;xFY=X4qpOk$MyiCA{Gi zeKFZoahs!KvsC^a4D}y|NUog}S?D4{;58R9zN{ePqj`;b)4Xn;)3t3`HCc&k)}ljObJKFGa=%s|+e<|&pg@-i;y`q&ler?b|z zl^W!zecD4}=#!u#nT}hp{xr{=2OYj+hkJFThf@^AlAE_Rfq|R>>%vD#!n!;CjHQ zEvVPp0zgpL3L-b<<~p(* z;2A#{brOKx9nzl5{ACgkLzyO6cZ06prDV3PS_LnRI(O<(+b1`gJ3FDHq|nuY&qiyX zz|qJ2CSlxslhDrQ6WZwlJ}^bZEmeRTwqy)i^Mp=I(_zX7&9506C4(Nkacs5XZ2P^$ zvs$5h+P9ZS$t{wp$Hx^++i`n}WzTd#g3 zf=i**TNSCh+PNjoBnd)#a-HM_=;mS@?0r4=uyfiUK&mv_iYb@bLWRmG zQb|JU&rd-!Kgt7>E@WPJ?8B-7Z0Or;j=wc$TV0Ii@L^-BAEoI?!e!lV6QJK9`)*~Z zVVuMQM7`3nB#oyV*y56eER!+r*E~sA)O92(jas!^VgrGM1<}=tk$IJYd~`w}&pqqN zACG0ha`U`>PH`uN8HqfX2eZrS!y5|Ds26d;&s5NyTH~ibb_V#Q*)*MBz+fpPE-h1V z<}();!>o7H2{D9d>axqXM!tFYBiGpB8zPS&N(oP{GnHd|SbUX6C32{tpx@5FQ056s zjvz+#4s9HQ*R|btYL0sjmK=ic)VNU0R9Q4j0N6+H%Q9aoZQhZ)N9Wa)hwMFlxoEvK zT2>*;M7M)2f_uQbt;i9YSY)R4AQ2__9g`tQXv}OjmsG+&SoQ$p)-?@jVeR-9jE|4p zb$xuL>}ztbsHNZ48RO0$`cy2j;taZN`y5ClY?Ny60bP(1b*P{ zbIJ^lE(;JT&9k#}$8zL{0=;Pn3#8#p{%N`cpP6RL`oqj-b)U zPE~S|JpaPN2V|>@Z~=>SRT%|APiul~7N(_frD5cmD1=k8)CHlzMCi|j26@T!6>VRYo`0i1st)Al57=~d8 z`eHh^*QXe;gIzsKyPNOxKx-KAj<4#X)NOs*!OOG+TQJDd%2_zgg1D!G)z1MOZc|gC z1O}qmH2euSicAJuZ6Tx?8ZZ5N3(TFiopJ=n?h*Z%VKv5UeehZz+zEZ~pWBdEs@FpR zo2%gGB=8PqP!SmLczxmAbB+RX(W)LMAJgt<;SD?Y4h-Hg0*N2*l*s3o#z}KjZGYCtc^ciUS>tYrIek{wq7t5TJy_>C7H3tBL>e9INNH)VH!TE{mB?t z4Qz%nF&DJQ)1LJ`8TehxO0>QdNs1>Q*3b1{XA_!@qwNiHAi%c(j9H6OS-e|OFz-ts z(1&Aekp$PVz@se^VJjNoXl&0E@r5{es@}o&KD+gJRTPd=y(S%^B^H2r-3{wMP(mRM zZtfIV8X(=LpHriNLVDmnPJ{8LXZeJ^c$D*8calp`?)0c%5Mvj6bgREujyjr}V`@xGRSL7oA@wukh9fkO{3CE49 z%K0}Uo4?AFq5x#;Ak-*@UO_4~GSuRX?K>mqn;=Kf! z9T|<_umM@M?aD$78n|fd^&^SYG=hT+0M2xQ5JiDE#$-JZid>-9ltdQkts;+*-h+^7 z;&aEJ7=Ynf$F9u0%J^q9v2#H|-%A^oMUJKvKLpdQH%KVv9l|-ST@m-$Vpkvc45tU~BYIT;c;Y$|lCI;^Y~_d4ImBdX@_IIa z^tKY8TgSep6WBc#prg}9qc~8IOFF(&m0h2w37&D$H}H#d-X??z2d}*exPmc@0?T%C zq(Wd_D}c>CdQ@7u%yS9phJuwz)6M^cuyOJc9I ztJP|EwIBTvzZAI+F3=c+_ktikFf3hznBY|QAY@^Yt+t1=qj<%v1Mzy_HUGqLJJ5u*mXIIBo>e?w|IIN!2A3thvwOM{u$Jf^xn zDG>CqAV97!#pt0&Rs;II^E)88Z#dr_TZ{$v($>?t?n#_5M5!O4~u$9@i`kBPK$S*!IuGo~(M+_Vhl zmx|d9$|tgpbz4hyP^wED?P5RJ5~E~9DNGH#La`Y{Sok_KwPh9H!TUe(;3J&coE{UU! z?)_qx1lOT;ST!#xTTP9)?oFaA6ccUw5D(L_`Biue(m>qK$hmFUjYCv@7qTFDhgclH zgKBU2uws=2K$|6^U|+)_i`Mt-I2(p0L8*5|Ve6mU4A!nKAw^l`jW#~IY1UJ`JcHzB zdz0e>69#U-s9EmLw0REl@>)9LRFy)aIw4rC8x!u%qmlWb{E(t{K;ro~Kq<;h@Dd<# zC^FOs8s#(F70`{T}DI#=L4qr{T$z{2ozRA3DbO!JqUwnk;xeMhmVp(}7v7J`qk>SBJRiMvJ> zAypP+lB~IKec?+Ux*)oRfmv;v<7V|5sFM15E3#x!rlR1=K>}VhVyV?{Z~(xz>t^uv zq0Qt8=bDdQDN7D<5e;&0n<2DT9{>t%r4jJsmCNx^wKfey_Ya1wS2bi|ahR(^GvSTZ zksd%d=!<@6+*i4>fKp{c4cl5hn+2Yz8;(yZbTB{9xq7jNNIpJCdwMnM$+IrqyE*3Bbd#aAs3Y8ya zntqL0*K`5MUT{*RP^iEzW=h}4V1lGaXYvFj^sB4c$EGBQ`vv6EywgwYuVjqU(` zL?vL%Qja(y8m$H@62u8)rzS^>Q^5wY`})&@ma&h5--{CUeLOPz!|ezri!%;@Rc;g9 zPV7rvk*_P_IH?RHdNnMebZFvvy{Q9h=OJCV$a_8ZVGLr%h!a)9zVvQvZU1?av3pL2 zYhy_crLfwUXVJ`fvUzRz{(+adm5Rj$DEA?OwB+1B-+==!D|pbBJ9#QN2@?t_*D z$oGU4#a-`;5u7y&;jnkz2_j;{jaJ(k9N42=igd&g)|B>@%V4F8knj#xtn?2jWHJMV z%T_`))!e+Xy;>T&dI_d+4@>a^C_tDzQ)Skt0j^hXEwyXmjbHFIx_{h+}!FY=NmK7>r~c|(E4Yw6@OMR0ekfNNyLbXn;gVV$J{ zOV`$KcL+Y`WRB)ajgG_0#=u+mQ*?Gc;c1sM=}j}_T`7+cgT4J8?deUTz6XmoQJ1Xw zR}$WR+_~yAD=rQ-SI`+zPc+xobmrNZ-|^siG}U8sT=oki-C`fPS#xp>B`gK3=zdnR z=gD-ak|Kv{^=2>}qOgd8^jKTu!Pgcs3l&^KBdBzSfw@cdjCzF;rtf{0&*({{UUf!x zCsxkGJz#P@%azvOB-u?MX5T1vqoZ;`$IlF3K1tzijaN7}RIGoGf{kePyOT36G#lg@ z+-kOF#G=|y;bRbkQtf)+{hE#`>M>k`BG8i=USS<5@_8fHpf7$#o+pZF`3|$Ff^7bJ zkau^MyfD>LZXqDhdIhL{e7m+IdBHsRzDtZ>(yGj7Rha)kO|f>S9(`j}@PklK=$WMS zWKX~L!4q{M0=o79Rd{i=s#R7bSEVZX{?MgBbNxWPDP7qJf61K_a)md2g;58qqZSAw1eUGS8>Wue8d7yByj0KFU-)p=>c1 zHfvYRE(1-n?cw3_h);6q3K{wX@w!r_B0uKMTV}te!E0vM^? znWCo^(vm1(OKxS$zu=v=B0Y-nBSN|QUIUo=M)rBG6>sCWXA@u`dgrE_EkUnr!|;gk zt^(Fy%O%|JJV$HO4-oIVZ;!dRQWZ_o*{-6Sv|9$056DIR91~lz(N4ZP6oCUXQ1!yU zoP~feTQbo4W0In;cZ%?5Bah>_2_I@!c91)Np1t3NHS83H<>86?k?2#2_0ll&a_>h# zWA^9SqAY@A6>$DEW%P(9_$nGu18BniCjDJm{0nD&uAfng0fep>Od;8 zM5@PDM~Sy(5;CbPu;xoI)tIYc*?L!oL{GhOyr^@VP!_Vyhb2%?t=pK%nSV#;N)__= ze6`9cgU#xHPDN>53XAQI;hx$2=k*4&WH+=L@fV?)>LR@p0B%5$ze`C3y3d-HDbyhw z#JlNp~wcZBHldB{XRIK`}0PdZZMW~wpl3f(+ z!eK}>D)!}R7I{9V5;yd7TxIKx+qF_SmJ;(|g6*h{G`Q?dgTAJH-Kb~eB98`x^{U+h zmrD~uC*!j;5upbHiE&1Z>it6K7ztggFAFjQAm54YoBF;hKQ za{q_4I zNdqbE!fjmq?<^IXRC^-K9U>`zPf}APh$|X#cz7XhK?A8wwKTc9E?R|xJ{6j+6pSV| zcP&J*SuU-UDVM3>^7VI8+;Dpfv}jU!C5o!dq`ASu{uuuHveTBz3M-s=k*n;ApVTy;-(MG^D>)N*E*&$IG--{Hyy(TA2znhjAdWiDs1@^cU`;ozU+%3 z_9qTzpPW&&n00;4i3nc%HNsn$V$7RCWx#edCZ!P+;umt+&^pn~5OAis;R?m(k;9SB z&oLukpO-u2w2C z6Za55^*c3UQ86ZorC%2d&%|EfxCJjM}MVGAv3 zNU!a$v|djZI#m3`fO*P28Ee}Z3Ipk}AlrkFqA&{;Tx%>SK)}GV zetop&4Sc{!_@90bWhm=?@;3=z&wDpbtme&=w2pnq)>$1aZksR)a}SgyGDGPP_F}38 z#Th&EbvvT1sVH=gtt4cQ67a8J+Wvjqs;*xs4#+@jR@*2zP~TR}$&v5vagCPm9HXii z+L77Yt=<$hZQA;Rp}^plYBmNaujU19v321UOTw+dsRWzsnlqnqe3zve`*0g%4{QDJ z*hXh*>enQKC6q7AVcW~!9|JO+@nGDqVf z4em1j$kR2R<|`7W7TC>P&%Q~(N1Ne zb0TCPZb6rq^6Hja-G2%Z(lW;|hG1%(O@V~McJ-y&*tT%F;G%}nDSdCYxTZ_Imj54{ zkJ}fK0j4w=bKIv&Er64K=$v8857HR(TxyIqt^-i0Bg85T@p^0|-bEPkCg&zpBKcFc zlr?N{9AnW@E`vD^g7``3ao|RdMCNi|xIp&|2R9W!d2J?b70U$g3*u{vZRZFP+Xr*T z$u@YJaHJ?voJTWa#mytp$my;Nw9Ik+{c$N9+7yMk%acNKA^a4B$`M*Y7^t$Ki-)}h zly6*3KIzTR8hZoA-vL*@WTyVB`h8i*zXMm6gM=Kcg~&WO1FikWE%>g#W? z0ds33qr{T=c}5~VeOZV?elp&sbo@(M=t`Q=P)Nh0O1v$UroPU{(OW>nLedixS}YeZ z;Q{2b0@AjsKr*5fmDyEseGu9Y9|%?ARpjr9Dzy)j-f_2%L6>a(;^i8X18;d zqxxqR?N}6oo43+uLY;E@rc!1ohQs3d{iFrapFU?5K@<)m4)dytW(#z^4Ss%%Rx5 zt*?Hc-DK*{wEiJl2N2uKe)TS6Il#LP^rdXhyaDXYf1VD-L>rrWj!A_ne_|tu1S@~( zuAzLO?07ZrkM5G34b~AE#cY9b-*J^z+AZFp8LR15G$$Q>i{GZ{a%_%$7Y*np$&tRc zD?+y9DUXpzGhn5n0TlV}mP3BK?Lyf*v zcNjKEsZgZHMkWj(xq`#U`qO-<79Q;i%4BljOS6LBFbGp-Ggab_uK3x9X$!PFR3f)p zZNAxg16-`#0FX2v9-GU)B2JO7!0fLTnm5Ad7&~WuWhRR$R8~H_ma`j8Qu0puD@V>F ziLeiV0|cpjDfBhiaG`<4@CLEmHM~Y_>qIfZ-Df8{Z|XmyYW+%i&5c^;89jtG0wF>y z_#lIzAEWKpYTu37b;N3r-*n7q{5TXWX)95rbuX`|*#)@JHxsFSY2^CDp--%P*LVA< z7?3v!g27hGjL3x3=PwF1Oa@Ss<1BsSm+-%>x>G$CI$X&7N}|*KXx(F>^dM;U0(nW+W;;}%MiF(aD^!gnlZe`_p$bH2 zs0Z2|`r~ehz{gKCKZ3FgEpD0FdsmgYrg0wNg9(bWIEL$E2nAest?>=u{TGJ!jo00M z&{KVa09hyI0}6@jm32&0Ag^-|JNG%$lN^IS#Hr$Pht0)cs|}U|#Zl{LN>0}JE2&AX zVBVGRh+#Cjz}EtHPpRC*rTLlQ^qXgJN8eR7D#xte*XUG_#XU;aPR}2PXK{?vaFuLG zdtE(uFJ55XScl=)A4HyHHYNId5RLD@7s_(*x<=)dKm=!n3^3{E$saOyg$cgzCD3`+ za|7ex(|-TGorpa*Fb+BGZ^-%eS>^j`o+4!6_l&&+Tv}eW9*IQ*AQdd6;eWl*YVK&l z3HN=WI)y1pAozLQoqp+wsd@LyP98dAxi0;p6P9@%WUo@4^Dnb3t42M59|Bwk!LEq! z`I7ra%0+~?XE!Koxrj5TUZbU|rOb>kcfprq!rK4cT?Fvv5#CVRSGYCNW4U03qs($S zQ&$;kl<)z_8`9kuyVRJGZ+1fw_v~jv zq-7wlvWX9&VAXNnhrb{Q-&yg;!H|6>QY?R7NHDj1xOw^+*9T+QeYxEI)OK;Uf)Nc?;rEVaFF5n7Nb%HN zngW}8+;sbsCPp(4y7(P{SmdFhPwez*U%d4eJoHlI`iEQwE5r>a9>GM~^vDX;XCpg* zq8ovniKN?EXClppb-+TACgj|w>m%u?mxaAZEW{OsPG!*uol94_DiZ{ zA`#GzIJTO75xipn5|7@T<-^<+TM50xZiz6#xp_kXoX71TZV!8c+|zyt*b1S{P5`|Y zTu6?U7cpy(aaNg}(aFjYyhOJOqydkEE|Ho(cV;cV`k|%w;q*~04!I8Ff!4_grFex@ zD%9pJoXkClw1Z@91kZL%!1VL&q=-;F(BSpo9Z5{2=!Xg8x!``}*lxzDaeb|qhfe6oUw(3_5!LXe`y zLpo-6*>jPh_K1Oln3PF+6X!#ayrrfP^_3XY8#K!_xsgO83jIrFT!1~6)ADM9%s!K@ z|3ir{zZTMZuXC{yP1szE-=(*EFy1kNv0+8v?=k#1p97Yf*2X-p7fRhMPfS+Ui6~CQ zNt~GMj1xow5P;_rm4mF!{Bd3H$1!^nXrFSt3NMh3RLPPE2?^8!-1%C{#8rO~f;L{v z;l&LIooNXySG0smQplFB$_a{y+Q*t5$%a{O1*VJU>h8nS`a{jBAkf_h(&Y>n+cpci z!xkq@EBt+GqQpRQAhCv@5mmG0RX2s=IM%mT#ObKYDzDvb^RrP3)0MeSx&xtGaJm<>GV5XuL~L;MO4|5{7e&w!n$Ns+^&k+!j~ z&C~}QZy->Xagt**(&EK8MnZDIVq+D0b>rOt6~Oh;0u{ob3`}W;3)XSDWiPTgRWmy+ zGyEe0SH+!+#$|lgZ?1`vIC0a9Gz*$apvdayI~w2T?|Jmc;F0B!(q0hN}`Wo zunFn(s|dnV!N(0swO5{QO{sS`Q0j6C44ZAH6-^E)b_AFnw;ynHIyzp-Sxmn^YM(N0)QCxF9WFg&kY zYwF`j<~cl%e}|{Pm3J$#NapnHYac~fk`gzCU~1VW_}LBw{_dU+&z+Y5P7-}B(pSoC zm%%1WpM0~KR)(c6%X{OcSTqg;cIPcICr*?pg_SknJt0wTPGhl1^kk-PPv>~$LOWZ5p-3r z25ng%Q2TwZ+T&D#aVs@`%nC-A;@xSV^FPqn z#cO$TOj>K>OBOC}Ok_Tod*v-}YSp+GEF)rfUgE;~9AK+k24){*#lJootfm@l$(^Bi1IG+k6~K`UCzn|QF4lBeRU1pz zT4FxbRfZpjuCt&*2Zu{z=O({RD=P!)osQ50fi|LHeB8SVMS%R@<(}1dH&>#$?)^$-VejS@XHT;F5$NATB#C^!Q zivZ!GWr6kUMTg3QoCq^8nB0nmwkNm7xikBjx(A6d)rE%XV*LTVUf{h6=Z2eDlsI+L z&OJ&H9BeQdPg-xEWzmp<`In@`Yb0tm@vSg@?fu)6t_A3H-G3moj6ZVyCR!x~N_IO~%Obdm;>uwGTvI!{6Lak< z(~?pI&(}4gVa<7PMH!bG9=nM_UK#eN4C?0n)4W7l)syzh0^}BcMi3AIj_8mHMgaNl zk3>n5QnnneFt4@lxhl~?OYUWl)*7ACbI&G{bOFH0tYQItRP{bpSk0AI7;!gp-ye%T zGOi=~L?zX6J_d0-Cru52mq@Rv($>bp3q11j2^6iMI`RPA=D4Vnp zq|eeV0;t|pP&VS|ja!9Z1q~Teez>fxgiBUON@aSxPfC9m(d}743~KelwvrP%1jWT_ zRrFU7A6&m;tW*X}fCYUiA=>6O5{m%}wGME+#kj+$x8Vc#dwn_F#h+Ob_dAc{4bZb3 zP>>$;MNG@ND}Oo77LmH$D%G_If>MzmzKTrkQyJjX6AWqjS;p2+v}8< zYSA+J(!sS7XEEZ7Gp<1H4-j-CPM;&3`g&i&GCNb+p{3Ye>`e?O0jdQ)+`A2Dxqkw= zqMgmRtT8+ zp-ar@v4zMJhkLuu5RZ+D@wN&Duex%>wXBEr*3o;uxu*MCx(%lY?N3+nE_4z2DhTs2dH^yb!%PMP213Ra~jW$Ux(j3h<=gtJ5?mcI5fni z7AM0hj(Cp9EUJ-9tVMHt%&2g?O?NwC3iMB4r%3jTHLl6iYT7<%#8yqGiYpUod>3%B zBxV2{YCzj|oKkUl6NWmsMD*bjovD~|z#A8!4`1m?gTC>}`0XUJRAjdP%>Nd?)rmnYB@TcF2 z2zw4(LL2xHVW3^R5Dku@9>mL~H)N@HELkr#%7G8`qz8}hS!BYy%f0>z^Oy|naobCZ zpyhgG_Qd)t#+z#Qi)Jtl&E2Zy3w19QDB@0Q0jai~GO$53H~qyopt&Ldd!YH3(^c~2 zjILA)YM>y>k~;t>kJ0zX+TWN-Wv(+V&P9{=a-004#x;s|p2m*rRF!s;euXIE%0Pec>iSXP@lj=qc9KL!b3aoWTtnl#bHgDy7?tS$_kpY{`A-HCi4?J3aOYYDe%m{2eND-z$-X#|aQbMos7)IRBN z@ef=9w1A44H0mB>j_RsGemiA{!j}O1$!WQT4PXH6dk2_NSK9(8e%vNN3-#~a1!fLg z*#-vG-uHnScEgQefc#xM;h*6cG{|n#H@N>Z_n)Bf8dSHU^KMnI>DPI|dpsp;dy>AG8&MIMwY1&SManq(h$J>dL?Y0Ds^o6QE?L``P)UXr{fYU=Vx z(i|LX*hnWhspbe}5Je_qk_SNMegZcDMNa_#|O4Kq^DoE{1aKh71?X)LkM3B`-3x)H_&awGCl4%mi@on|lg7i4WAO7%IU+CiYDpbR_w3mYge8kGwcc^na=JhW~?j!xnC zxl(=QdTGPs*LaB?|JOKvn$0wQ`9q;p37!OlX?oQJ=B^0BYCfPDTA5AcRO!!B?R=6A%s;F>A9AF< zjt21IqT(YFZ}e!uQ^61uYw+oX_y0^Za|%h{)F@f zJ$0!Hbj3Zrw~VHb%~R3uo6zOmUfk@$2-8I!v*3zk>0*2c&kgwB_OSTrChKv}UyrRV zgts4PBd{Pd39td%0)sjDDPQ=|DSN-YyfLp~=L`r1hPNCdZ@}2wW&QUWJVh=7N6|Sc zr_17jTCdGH@<5O9So9%sxDp9%PJ^Qoxr8Sjer%B*vqEkRqORKwrpX8dsy!FIkTylF zn4AztpEqKs3X-?2)LCgRC9x_cUS8P|VzV(uJW)Qd`8WXC)2k#H6jsZ(4d21ft3157 zsXSb-2o`3bMmOrNeSzzr*?j-VcgG{R9E(Z?|K1zLA>}hhc)E^UBmUCvlvLL*-_x>o z`6yboGcp0J#)#4Cv8rR04a%CP?~Rga^n(=&u{_7Z#{NNC-jCn~-6M@sT@yc&cM`I@ zPcO6M0;TakeU~BG_O#X3GaCC1b7ZRL|DFM{T=kk^Nrerkvs?3q75aU7o@hc}E49H5 zc%jse@4YRSp%>m4R}@)5madh=Iuc<*)`LY77pJ(L73uY!R5eug5!j#bSQ|vj_pV(v zpY4bEZvp$@)d+THok!Ix-aRe_GNCR&&7+S@+hyQPVeI(y){DAmg||~={LJLsX$g8b zhp}H3f=H^pFG`qQuFS73Z9}VUMpTO~N+WI(N!>dLI;D(HLuszrPG$n$QX;ABCd)S})2$9DmPoyyHD$ zdH3sUmfv>A_+cC!xJTMAd0hUU&*d<`<}$q74Z-rfE`T@SsbIEn zob29uzxGxTDz62g(!Z&KIP`3hOin~e*W76*49@mZycSfdZFAKIw4Jk zub>)5Yka6|Fb`cEI==;w$ctEyLq5<4(ST#n@e$^c!$>sM8*Z#VkzC=}Z)wf%aWPz{ zB2mMKLTXJD@F7|aOJvpi5I^lo3J;^R>T?73!~<;IK0Z`Suhb(hr4*j&gCX~}aG)tT zy9Sv7x5Kk}CJR8v)owY3K@ezjh-R)uIw|}SL&tyt_7llnv10rf(cC1Hjpn)QOg10g z;B>afWIa@C#m)oIe28taGm>3LXQyur-+1dy)MN2~A6%)T*BTEPw}S>pWNZugNe$|` zn&sSlY(i3!ZOMjD?adQJ?ihqx^eX-WKOEl_@bkUbqnqLwgdY5S_U0S$y*DD1fX8zw z;A;}#tY~k+xDMx*FGQ|3;1%47`{EQtbwxh$%tFCz6i6$)H~qPyyCB|c*oYA&1E|IWjk~E0KEAnK%=t9+|SW(FvYc1P}zD6JBAxZ zcRmBx*AkzDXAbvEo=4)@YA1}zUIQP<>=ug|nk=uj^0en!r1=`NNb`NnqPI$qoyDc9 zcqMQaa8U-AmZhe6H^*43xGPOtPO+48!+NfI6*G%3q;BuR`EPZ(p46482DW1Lc{plwivhJDeG?6>Qbgu*Rs3`DxcC?yZ)m_V#FDh+hU{#v(&DV$Sm$Q4JobaHKT;#(N%a%NJ zN)PY*MpNImj@|Ok)@`jJh06lWszHNSg}D~3XRFL@#aIp}>!tcst9&s{t6x4)DwAud zRF1}uX>iU=pX0h+S}N;Q4(KHv__@KJ#gj9*p-wQa+8dR>;Xz~{KIZpSc!9M61>Q2Cp{vd9~y^WR0d zWP{jxyR69>Wj5R(Ak4Yce!NDVd0iQ@Y|%zjRj}gZ=~y9B4Y|X@BTvZYFdGZ?{)f`k z59BaQSDxR5R<#5I53wE7%X24s=4NVMquYxxW~;CJ?hUU?^`S)ql2OAmQCSVQTfN=r zaWi)SIzSzLqUo%dDjlwzcXPNoeKNXf<2}a=VT)t&R^?gocLSHT#J#?7JzZaoUuUY6 z`mmLLhxdiKC&Ze}2(wf(vS3Jn4Sh+`-IUOw?hlscx&-WMl^vasiEZx@+tJB#miGE` zFwVuCK2rV=ydreajWc-*c2m9gXZ?B&Wg_9LOZ=OFd)+|rIiDQaNwC^C`xt)kK|jYCu6Fu5 z7#gy-2`}{rnFx)VRMpl_(3mngq~>8~(VO_sI}FY77ljDtre7Yno~wnZ2-B>yaXM;y zV-v8ydzYzK&OF38+kFJAN*HL9&i}o)ZZwnahpKLhci0N75Tr_UhGT#b(v#X};ysWX%z-{LMdjH_pCkEaV_pG96s6{(NH3=p zkMZ4We6g~4K&)|b0RB3UW>bt9bdSW#u*XxZi+1*F7g`D z9hmrMv&r<*7r#Z#mMGM2hby9~g#znkg|}UgW@S($?2&6LhEAVS7B-NNBz>ue446R6B@t5np?)@e%ljUDZTeWlo*}>$aslTE>nz|1!#}^>kKXRhA?Ld#GGTI6@*299r`EBkifTol z4d=Aee`~ghhGj|%-_9hl$i+pt+BAs?u2_paz}`gUP#+-I-wNpWzNhtCy&}OmN?wV_ zv|q`Z8ymBg7zx)O(>8Xb-OAuR(a(loZ!WZm>`}#bb~QSm1wi|z@arh;?Y`sA=z%!Q<+~P%=%?U&5=G>k}sisGn zd@8e+Xn_2voUA}2AisY2__CiW4iih3BrSl*cKm7_?!=Nd$7le|Qr#TVfM%>I~vp!;yLY+%{iG23v2 zr>vU7sJ;1SjidUB(HO{$+J9i5*SRTe>l?0Y0XMGaoz+>SoO}G$W=tB>wc;{QW6AIn zbY>7umk@%Fb}q@_e0)51?Ue66*IO%BXQ{^ckJfN`t-YfqVC-b454sCqT4z3(2w?Y#6piQ*8ik)io&ssfvUm*o&}|5& zo)5WAOMELQg8KT$tt_r-tOf<^X!)=g5Oe8FeeIR*UfcaP157_qWLDKymME92>6VlG z(GRCTuCC(biDT|v&-7%)`P^H5KEy|9iwn~}vw_X>AJ8s87@~PTIry=Eq_UxdkM~Tw z_1I(>twGuIywN|7Gzf0E!Ua`Gy+Hw7;AeD`!DfSZCi{?`FcZ0Lj>#guuVbI-GKHg} zQfzh1SNH~{X}i!bE=!>$vFm3aVbivM7%)G`(@&h7Y58z+>W$UL)T!XAerygcNkuiJ z57K&LS=ib)31J^}eLi#{lBiban9>c%^Varo=I%ZL$AsH!O*2JR(uJtsX^;2-+t!JL z-!f0YAkjSri91G_90oO}Aou-|PdRZ1u}n!jrjGpdUbnVEzL_kAIXY|Rmz?eo6G991 zBMIy->8mS{4}6sQ@Vt8A?()>JURqR~VA?G49o8(r6M4B%`2|DWxdGTOPt#&uF%pcu zF$nL(TvrY`AEHP7AvfUy1YPf)NRd? z`Q1{}3KLU}1C^wu7V z8NgfJy^N@q6XU9Ty{hDneOS3;)m7bgdm$j_dg#r(oo5YDGn+U~nbfXGTmzz}4(260 znyJ#Thz&m46r@UXGWH1q0;odgI}EjBx(Gt`y*Qe{yBR`29O#vt*r9iaiQK8N6Xqnp zpqtwg&OX=uIt#yrPHd24i)y(&(JyK$8KjPoI$){*`CH6?6ANjF`49~mb zb&uQqz;zxFE$p8d6?o&F@S2Bz_MTI2yI@d6kkJ&dEpTqDbIg~;Rt9&}S_22Gpz?ZB zC}n=HuZ51VvH^;) zce#Lb^W0t?DwNdr?w7iN&b?Lw-rYRzarP3o-Atp4FTOed{Nlr(&cFWn$)kr~T#l^5 zipUZOqeHJHk^mH%gF2)KDX$2kIaqd#9s0v4_RvjqOn68J}E30MxMvIk~E4ZK4#^icdt z6q<7z-5x7dT`LUO3cH!nXmq->NzuMSp-GM{=d%u0gXnYAm+J?{r4iKlF^p&7yOXDK zS6vI-M8F*u!p^Dr5cE@7pdJl$U8-`qCmV`aDE%K)ZBv|eVQ-r`80X5P2SrOwWP#yv zp}ipgK?_i`Av6=;=Ii|M{`5C1o)eW6in{ss|Q zPXs@>k&|CAq>3WXT-v-f>uHiK5?GlHJ8Qf{7;P1{V|>W(Mx@?Gsxo(WeGp%0q874c z=sRoD(uqt%QucK6{cs_P03pTc{xQ5rlx>luGg)EV9Wg!+G=d1CQkh@b^vp5yr)~W_-bNWElL# z@&ULVc__i?9nDh4^Lq2<^;KMzOP3_AszO(`a*+?)L8FjhjyL>=kbSQN+y+U){hNj) ztM#qtrvYcqS%K4lmKA*{9KN=dX{>O$Ri8%uwdoektA`H-7t8&&vPM+ZbGi}HI!I#~ z4>3$-B8tQXv{RNRWpy=+p5pi9_iI2pH116%T!UU8Hp6boUCNuMv>oj|kS@+X5QXPp zjlSmC;Y}CGPpHt*Cd*X8+F+eb=13&X4Lkc8dC7e693vWv&2zA1Ulr*sR;TBU6`Z@@ zv1-!_R5U>EyBA1~A27Eb@=BOh3u0}KR&_hYjn!b0^lD*#VXAFUeG6yk-=R#@G_?sr zi;;VmhjD;sc^kC<1f}V9c5K7v>dwh2BMhrE6;yMEx6zu2~4BphXUv*?_ z6IpGI0#BWh_foy8hqqW_tY&4MOWVe4HR0-f7*Zce-u*zPs!|rmNKn@Ac5Kn!&?aw= zF)rF>?T2wbKkdE;aU1Ow`w^q%f7IQMICk|`;dfz+G{}U$7Fw%Gio0|9BFA2u;{9lJ z5W@ZkqirmE|9-%GjQt2J9BGri-Omd+!Y-uKrkMAx!WXkF`v%XsV4Z4YUl~QI%YP_g z9VFgv+4{~-T5$uoEc2THH32hF^25&Zw70t-ZXyb~@M9eaypN@MY=kI`wsIo(3N<^t z{V7y5d{NOU


R(Ow2HtQ)@i=J{qREc$R(U;v>g1)XmnWLjlfuHl3=%rrPAx(aNFS(MX}K>(k~$ z{N2EKZX(;+S+~<07PVP4563d@SLGRlA)R^?<+^8xHlqu z(e`2D+P%Xw*w5ZEW0Og^Nh3kzw_W!UWK>sjB|OO~4NfM+_UdW@+XqGa_0FJo|F02ZJeFT$VqHa7;BX`7GfOc>f?uR|Lag+Glcj+$$hO=gA0?aNz^pJJ=TRm%oNsRAoOl16hpJc{&)+ThKX5&omoz&(o zd_z(jk+eTj8>H7JwLy39q=vMYO$7%?{5=W|KzMz@!H3h{sciI(4e6{2$o?p8kY1bC z&bZh+xgpJKQ(|YS-Xp02;q?h!-G#6gvL82)!TU2%qA2b9fzXR_$LLwqzNSj+6wVV$ zYSoU`SjXbPB*d;q<=%UJgDn`1n`Adod{UmGF3E|nbgxYTGq4OehP`DaQ*U*tzNnEO z!Dgk`(#;(>WKd3JQO^51aGhi2wQPQ5uueLVcG0yvO**kFVs>Y>A|Il{5gbLa&Wf0g zzMB;>bNQ#Q2%fNm4YFcaT#ye|Jd;;i5d{8EUk@~uc1V9Rrl?k|2sf%$AeleHen^Jr z=^*6c6#^qyCv9#g&F+nG2a%T!YTN5-SA|Y+t+7d_Fio2C8M(8f#;^IR+g3a7?-<>) zj{bD^vyh~N_AaG)YA-8U_hhZRjBXWEy?7Df%N;Hu&10iQ>{StQ6Rzl{0F0qRW=epR;R znboubU-)n}UAw=XeFb){cJ>y@HT&5oJUI6(CV8GGv_iFR_6D!A8Y^D4u*P|DO~vs2 zf*S2g8IBSx_HTst3G!8wYGhEu3ySj`1(j`iQcjwcHI{T(c9jR+9M_ZZTja7YudcLQ z?Su~JH3NKOjtgYC`f;vkWD1NFzeqe?4V$^bo)mBC$pfne479Qp_qfzAfXZpr{4xEj zYO2^_8s51>dP zd{kt}ocjL4ZqfwY_&B?7@hT&sCTw@-|r)k&GOp@5n;WmnVr%0!`ZfhfB1?7 zTMOrrea8=Mn5xuCQux=@goZCU1i*a$8wC#(RFXPtfQC=t4N(mJlED*@jiukDAD3JZ zwYB#}$q?J!`%yM?1#*fkVyGnJGmLiP6t755)#L^skqEp^lbk}NRNjF6smNzQod|0E zpT6_f$*@+iK0{?;5`A3AYlT4%c3vFgAyG&rx*gQl^~zXGez_Bc>E=6^@CgvGr%rK} z0pj_rWRJv~Cze2&!tzd^OEKk-%o7LtmQooGBCSlERj#58o@zj5QkG(znNv*4glkMw z_9k#c$^AxVnrccxkBQfhZqy7GJk4Q@20$A3$H7fmPWAoc;{+Q};Q^>)ZcjQB+->gVU7YOF5(G zVpUup7grPfAD@WJXXPQC(|om|`>J?9G*Nnb>0|s*bb24oy4xu*jN97=*OR9`?UPJ9}_)_-@b)@Ab{_T9yc3 zT_s{3G*kBE;7g$EMdi~jls%{~BQeUS!-%H%Ztn=2(ei0rKE>aHNon4g!7I_L&<*7z zl(c6HN&9V@pWTZ_AIs8cO8E7;#-r~tl%GDj`26AJ#iNJORoOLcI3YhaJu#qG!7~PlCsY$; zyls{n7%~Dy4Q-EcqV(r5I;tbO$_7WEKzs}IB?r{7>0uz7zP^x6KNU}*Z5J!^lUY&7 zyu?QyrCFBhAU4eu)*r{`k);-bT5r<>MEhwBer9gvKR84(J!ayY!I|cV3yP293tt$r z!f_2m<=2R+Oi?E8VLZlR27%OlqldZ|#?FpG@eCp;KOe#KF#Y=5>(a2BBmtC#L1U2P z4{;;WXFwDt@Ny#aoAk?IRf4{`kf6*~m6jcSH7{>^lRu)Uo1X@UOZOqj*9T@eBe6qT zhddI~DQGAmtq-{RC%Hu&PUNp`_6=dZr?aFv=~aKRcP+ea+d%lQ2pNhcfa5I99#{tq z%eq&FwcVOz!#WHNZPBqdMf60esaNd3k9RzYqV2?#L`(J-V2{KxkH?Qk^6q%NtEEZl ze!&i4U;+%5Y0_7KjlFlEcK>tu?nWfpRQ+Ea=Koy01Euz#C-0P^t^TX_z<+)lz5}D= zHT?Yht38_@RXWk6fGWM`=0(sQf&cR87E2q;3ZR_B&W0i)^SrA|Ltz zFEWE_{ogzlhcgxy6%ua+k;bAaXa<#b)RHkq+xnmqn0_sSe1__?rbAD(>BHmI*4DuS z%gC9S={_|Nd#{w?kxwSk+e&zNMh*=$829&-HMV!~nf0knw_2r>BH1%>LJ4|#8evYP zl+xZ8@aK}Fowv^Qq}dHW!AxrLIYupWsXOJ z9B)8~e9<&ixx}IRQsJPhQF?Lj@dwABfF^MK(ZvVHPfk8~a{STogJXriUTiYJ-%C|u z#+K?9VKZb?B*qHA>(+iM$3K=cKvN-lDwOLM(XgP2k z+;E1R;E*35#nC8Lb9aPnOtYK#J^ZO?dw`elHtBNtQTLcaCwTwSuZNFr4j+XVkG^~I z=-HD;=fg*nSMMu7gL?c$Y3lXNmvasaZw2Y^MaXbfy)V@$6t;z?{S9^pV3F;hMz+u% z21*@N53b82Xjq-LhzbT&1Fv9KOxr=K#_Wm4@QyP<|QP4oz& zrx`E>KW^b5Uz9BJN)G5>i;Q3Cak@y;Ga_cMRl%w(WljkI%XS0TFS_2uQ3VN|Zzh`1 zk*vVWZaK&5VYM#Zs@Kn`Y*A)6bwtZ<@9*NNG*@@X5{A+e<|rB@C{&0Ff;xu|Wlz$3 z3A@uQuL)NpkNUu^FsbxRf3n#fVm;|R4a3N*XwrN--w`VYT8K>j`{JtT4vY#?NHBy3 zlwVO%0Um{tg`r-5c^RJIE=DUv(@-Mn?$k=5G{wQi1W2H&WmAUVI|)75=#E)eEDIjm z$R=z)HJkS*oyE>(O}~%*v!rD@af+!Z<+5x=!fA8Yv3OnxZRj|sUb3=78%A}=6}vY+ ztj3YJI&kU2im0jtJ%Q+8y&!VqXqAk?S0IuP|12ie7{0}tZZ_;Ds%w_2b4+s5gMkQM zJ17IzR1VM5Jkeg5OyJEt5>tdy+f|}kV;2i)Q<&)&mCP!N4bU7=GN*9*AkYZ&|p^J;zBSC%pzp=7w%S)DG_FR+UwOF{ipUo{_O@H+w)}gnRZ-@!H zu^(3O`W38E>vkRMJ|9-I>y$$YqyjrHZvsloYwhOV%GPk*3Rb@h@D=NCo$vRB{?mR? zl~ias-0GNqBO&(cdWhB|TK_+SA

ea@xU(7Loazj=6_W6@?mR7e73PFWHtFs_#6cnMU#& z-{Z0%V%?|k3&n8MDH~AS`Vx0Wl7<0-2Rq%OjF~ocf|`93IlWxpicR6t^ZYxu;=|fKWkAL7&s=zdV z&g0rLO{+!1)s7_?NmzC64e7}K}YKUOMKbh z=MFpmsQlKtda2Av>Zk*;{1$Utq&q5^*P8p)!b!{gK{h?griQc|(JXe%7wOkfAz}x` z^I_xcR5<(EICob-ANJ3VMYPNP6NNI$=Kaa#%SG9{6?fZ952DpZv~buqyvkMw%qt#L zVPPxkN5j0%@KAt1s8ri}hSl)n>rNABUm-yMe4d?YLfx{`p+Z^;^dc41D$y8<>)n z^g?kgVzrWC`=$Da-B+?i#`K>bI}S*<39e??$V<-sT6~@~;q$}`pKB#U{ns_B^K?-L zOqu)n%*!K_wWz{>hwVz2ZoXnnXO;7gnG0c*!wg|2bm27e^b z$pp-@8X1n&3@q)&n%546+bYl89AmpcatBa1DHDESDt{BB9pa37K?{JfeHXyiRx>rC znn53cuGM!CAx92RsqV5#h0eNHd5~euHQihQplH)(r@!RV6pdZ&$Z#Lu-YNY8r9|i>)*S;Rx^6DPxO_`*=jz7cKbcz@KAA4Zaf z5a=tF;^s#ru@`&6%^*iL=kAsIRKMh*O->!Y>)5?t zG8v6E|DeZ+MmJda-Sxt(x`6^*7O59yWn{0uB4b z8#!-+IC9=6=IY6^t6!kP_DHqrkLOyEbcSp9N7EbP``c9Hv-)gbL$g(?m41{Na(Gj~ zvW{YBR*vi$s!9zGQ>|n5c$$7W&z!5;Ru{lL>s9NDnr-lT&pZ6r$`Gp0HTazRS0kHZZcDQx&d7p4f!LPv(6^ca&o$iTf2+>mna_2o@~W_DN)4! zrhH5-h6F-hb4a?0#~E3>=4%|i@KxNCDEO|k>jCI^>+h(6$vRim1)3ek;X;@ApEvE? z)S!5E;G#C{)^JZFtk{60w7Xjt=z2#kv4GW@cUV96cz*@#?qWnJ@V!eBp}_A>M1%sP zyATlyeAc;KD|fG6&RF1d`=7uRoYr~=Qv%!Zaf^)ZM8smrZM~>P18kRJiv_d0@(QEi zx9(Gn4Ia8{_b%kr)jmGGBfh0ltP@{(XBit$G0nM&cOPiz2R22DDAPoEHuf>*wQ{A$ zy!Bh4X0y)zr;b0Gk@qF^LK);|)Ik8HfV0CWDI_e|ryuk=gfS2{Mf2)-h*S;+I^rXu zEZ|d-X4I3FtNv>5hRt5{BunRuA)NTdaV|4)LwsPCd{eDdQKsjNhvqrsavv5^)gi@@ zvRO2oW?5H}qclk^LxMW6vxw0;dWt1Zz+xFfh_!Ws(_~)W;jBm~JWHdS2m%l7slu;e zl6*N6Nr)LSQ+WNCYD3wG;?g5``kvIXXj3)flS>}1;3vV&W(zYq#tBts|=Z;@JHtz;JC@t+jI1NUn;fEC=+N6veK{qd?D zf}WAt8wIYyI4)L?zhJPn5~!o6%vRzss(?T#HVhouRfvSv6y}F*2%|mim}O0&!pfCe z=J-VdubUdT6$WzBRw9J*#EAG7&6;T!f>KG6tGKQ5|+0XvCF~g1s?6QTF znkiEbk&Wp0V}&AYQSqVL4yhFP|Wlb0uO>F zkx&~^)2#HUm1zccMZ`3>&4f&&+M$@?>jDo_hR+S!2pKZcql{tyyCP!9Y%>YNiQ1@u zMJZQTU^mWBKrt`%IA#)W>~e|MDwq%=j^~PBK-FA7f2r?ue~3n@A_a$?xgN0Smhu_F zP25c(ZBpI3WYEz}ISQjOM&}w2Hv5wvj0?%v(3MmSQWiHgiO7KaAT#3$BVA>AxFSjX zohX=!&SRmAwMrc3l*coWvphi$K0>8#Ad&fyGsr`Z5#biyRp4QA4NB6zBm=;jLxtK_ zf`LEQNXZLdr-$$`z$h`d#XK2{aC2|wmRN=br#2;5*@iE(QOplxo?K^BU1@J)ktr*< zt@mQ}R6qADxc&IU!%^hX*XhRc57_xvJXSZe?osQffoA$JEE;OQ2SGIC!+_DBsdfwx z^~S=o;D#l0+7-nFDg(3bhI$TV_3J#kJPr0Fv_fX8?rpJ$2KylYX>by# zANTG_28tT4Pc-ui%T_FJavI+r}tY`MnS%T@a zHX7`astr~v6W=MV#5ru>bR@HsjZ3ZnR?z{qg(`+~b`u;0XPPkd;Zjy;E&I>bv#;h# zF@hyXmdY$W6(J8_9Glx3$_9IPexh3kx(Zq=+&Y5p-Us)LWA=RjcBfyBOtE0jiM zjirLA$VNzV#AH#4jsk+1)*{n<3;`%3K4w}++%6evYHd4S>LK!5zmz#~Bqs=-+Asp#zR~90?1EMmQwFe*}k<#{~|x{5TaHpxKV&fL_Md zO9Oq6J1-ODac$<_v$5EDxqvW}0ton-v!pf>5OA{NFz8T-0to$EZ5$*vb4Nmr4zF=Q zZ>KvUrS2=aa#Eps$BZ&nE-BAv`VaLr5Pe_$-v$k@rTjsLH&zRP4PXpt>Vc;2lJ2p0 zR4`0r2^ILX!BPwu-jdRCtOd@F3m2SZt{R2B4ki}DV)P9fmaGM zd;}fA6cKLs(S}G6Bw7vq#P|>(Pqa3@Qq)AW)1e@fM9Nt>Kjese*c58jOrueuv!Ox1 zWVdGApn5yY7L7WaQkV~2FCW5UX*%%Haew0;_`o2$6M;5<#aA5rTI>19GEKnTP0(;9R-o-r@8HxYUIFnKHKe28=qp=|0-s7ERA zBN5S?hvn>5B9;k#R3J2|LuajIt&W3Hy1)H9kmbN7E^4shfQ9=0Uw;5$Ac7}+HWbIuCp`Mv)e}Aq?{L?KH}naRPkb7|vp(vf zXLwE?`-7*6Ws8o$Erka?zTV`g;rd!1BhfoV-ejnmd&D7hqECn*48jvW8;Ypt6CHga z>j|F*x4TY(7Mr}~^#bK{mZswN8>Px$W|QNOpH5jSFT|-FN6~2#YA>YF;rGT2YrHoV zPZEFn<;BadD7(A~EiWI6fEn;%aC-jq>?{}qN8s|lVPo}o{kY4HgOh9v6>G*uhU&-%fu+O zmHS-}aqtJ{rB7X^;W?y39UAN)n}r5K7(4;f2p1gzv30PV`_)|3CnCR|l0sa4`I-sP-~av_ zEVEB0%*Ej7Wt|CR%bfBXxfz~ zzx`fwE^+Hg^z&k66ajdCYJv2Ng0&B|*^~gE8A~&T&3_B0mz;$!l6byEW@iDqV7`1c z+Z2HJXNs`9nZ0A%7sWy8B;<8!K}G^r-)N2geIg*{%5hpyUU!Y0CdclI0yg z2s(Ly&kvN*o2`*VeFVRXu3xe1hHpePiGWp8QBqzJO}9?w+q`bNOTvjU%2Yh;4dw+#;u?p%(0$TtY#@uNlBpkiE%e1|%&y$jBjoYm(w9 zFNVT_Qlb#$qBpn>$z{OeTQ&zHaM@rx{-8+lnv~fvhX)87-9bljf%xPw77q#jBWST{rC=h8CK}N|ZQhZ)4hmB%AVv@Iu_L_a~I&Lh{ z$y)IaA9se+mwlTaF%DY+U6=O}vgleKLM@zQbMm)_pTmvfXq&^D5X|Q>BF;Xt%}4~3 zWX@g3)A~%j)}1QY-O0002UZCX_T00000000000000J0001NX<{#KWps0N zVQyq$a%3?sF)vU{0|XQR000O8$!%IyMMLLWrD6gA7()gCCIA2cY-wUIZe?_HbYX5} zVRB?KE-^1hZ*OO8WiC*1Z**^Bb!IMPY;3e02Xq|8b#HfX_lnv{@|`T%I@v~IxzowA zWQ=UU1!Ef=V;f_LWQx0qMOk~#rdXCNIxdtDN`mQ$36MfU34{~~EtL{#D0U#B6G9Tw zi=AI)w%naU`50$3E3rdPdXorDvXLuWMSivdLM0X4C33n~t1!T+Q_6iq8Ql~QwJS=Mp(qi?-O~ne6DkHSPzY90Z~oI=r3}Jf zex(8FT5=Jv(!b}TW_Kg#EC zTetF@b>O~NA<|WadKZX5^_;x39N=4Yk#53A|NOuyus@5NZOagQtxgNSkpru=j z?r0zoaDvM>47{q|pA>Avge(0i87w6bbrMl05W^*6xIolP1OcFXO?y}w3odAwsL<18 znPMEqgwUAn%o_7@kg`O`$qbiX9E&-)09I&Hw|=ShHAx9A=1_c0OkM>ILELv z7uA@D!F(dD`G~kmbwJZK*0JEpB~)txQjUWMC&U_#&zg2snT+)j<8n0Qhex(WwHIPA zEt#!Q?c*_d_6hKO^@04S!HKDc-3_i`_n^=eN?H&Iu2~Zhxk$Aa0mr)M6{W!!H|O0* zh&K%J>X!{bCV~Ntq;Ay$-SDx_u2ifOgPPCQRQseLszbF-Mof!LQ&OR-m+)B|%%xeU z05FT<*OlqOV;0$XgjUkX_TmB~$2Bu)UcQ>}Zu|#v5$Pi?9mLs7MeWMUbZg4Il6gB; zMC2%74#Fc4-{Am*fa)PR@k3vNt zLDXBp_VI9hLGL*Rr{{?t-J>1Pada}dNA;h>UCk<352akL& zNZk-lc0_=UX*SaOU0Md}PSTo$aSW)M^QNp)P1p@mf|F274wdD6ozTH;gPOSAO{24M z6gs`1)??21+H0{~5XH)+s*PmX|KZqXoZR|s%+p1!y72*EIf>7rGL^fC;;^&sP z!X(Wq!pZh3=Oav5C?peBVIXoM_?;dXDbx!4)Tl5>4QM+2N!Ija{xGUST!&`Lc>6HH zt>f6GHj2gcc?s=18y?*PMq~8!_GEnC-b{z^ZG?yG+2r>O`aD*v3W`i%k7nh-=aSk2 zq_N<`Mm{aNuqJYu3Jqo-nl%>}x}OHRyK;`lkP4UO2GN#PD=f)6ovMi7>_pBX@QoWH z-(10`DI-er$;8b=#{J7XY>4q5&bETKBIqs`?y16Eg>DAt<#xYXt+Hp16J%P=7YN{3KFb?0D2wsB2g}VhL+D0gw96|F~7$Tk*{lr ze3Jq-Z(YE*-d{z}8d`eJ7V+xJfu;C-t)yqFwL`V(6lC06`B}K1@)K*!#Ol%17eE}Y zJ4sD;n5uO?!s%FsnPMr?9}a_XafoN&3)n2$HumX;bsi43xf0 zHMMjUO*%nMS~vQVrQvwMx>%8Uer&KWuI+C_Tl>Za{jJm|<>0CJU+2N$?*41h$KH*f z$MSMB_PnY7teEQ*%Ll>RLt=2iG3h?}Nx%HdSMNoBnB`AWwSf!B z_+7GIKn^qcA+-;qZygS9+JUcpZ+z7u>vn8&LYnnwZgWDa^`zJ4 zKrFEqZgc(%KFPbWeuq;y);Cdy*xy|Uks7&l_B!IIz+zLhRFB&5czg8pRSDD zC!cP;hm1qB_4`AN`-7pz{h=FoSZUlhZ`k^XnQ>myv@c#>CHk0kFqP5!<*f)?zX$H2 zwOzZ0XoFu4k?)Nm^8HHn^-5n;{sX(cgCToW>u&7W`?6wE(k3S*?s#%va;zN`z3|-T z_k58?h8zanHgcJmX`@-*Aoef5m9(*f6tjnUj2sA6>go=)Q{mkk2=$ z5N0Ew!*)Ls@6wz*aUc-Kg*WEX>~BHJH2d3%VAbpaWaT+a7wB6Fw$q&NVYo63r`elu zNSLiK>_GtHs%iZgM}77bH17wyVn!=?CWA+|!8J;K4u-DqCsjQUqqtpjp5LD~_WABQ z=W1L^CtY@8sB#P?7fw3j&ilAhZ~?9qfM4%{UI1i_jXQe~e<9+Nv23$uTp#DCOp40% zqB1GrxRPt2#1}I&g|Zi+9-D@&@x@{p?`gouyvaX-p0m{Xxv*Y)EUdWAw=V%U4yN0e z0!(cjgi#V$R&kZ90%Do?ZJZsfe;2YNZnm1Hy%|{z`$NE%N7ugx_||B22fAeuz;D5Y zyRGo3(G$A84S?3=09*#Zv$c>HRA@Wr1L|@BlGoRS8!m&Q5o%64SF6gJ+nQ5}uzdxP zZfmY{J|N8SXWx^hT~O+sIT}!`E3wpn7ES9c00aoV3Zws=i`ML`!4Yeycj5L%AZ^!E z+CFg8b`3E5(@+-S6fBN#0*1K>I3^<+Gnbj(#y)_!q>~}zqR7SIEfT?vJyBzM> z4`tB+Tm47@a=SscDvxq7Rh{3QGg<-`Hz;9IvR^8bggBHS|AW?_Y5kCVFhx`#6 z+}=Yh2hZVnp~=@|4Kn50`DX}BKG^Zs)AOy z3uAbPWB8rl3Q~TJ(m2kOKLTA*@4hVR-B%z4SGy;R){$hmN#KrvaD`gMvgIJ*PO9_o zQMmytr`t18`U-gDB8!0GbOQFz)Qw2kokR+i{BA(9 zRQ6_;3Ex8)5wqLh@zM$7W}G)AghmIj8xw)P3l9!su!X*dt+kxL%@S$S1o!tb6TT0{ zL--%2C^_IG@DS)9U=kCW^id!&swaze_)<@M^n|_3Z{sE~WNWezW4(zBkEzTmH@_c6 zC;u2`#^WNpA16hSU_XJVv)Ge=l5_ZRB>d0~uv_NWU(q^ana)0D{ShW61u|Sb%YKk^ z>0-_$=JoRDQ7?by3Yh}=V+=PS;!76C_Y-&&hWV-3{(szcy>d4b+gNHVvK>q@?4Myv zVfrlDVip(?_k3xbD>Q!!9vzRsL`EC~r~w}E(6+x-i=NT2o;gecNeQGRP$z-m5~xR@ zMNRfv4K6gog+{tiqYI@u($QGttS0mvp^iZhAx0sB`~GV1r>Py+aVm#>xM2Y@OZ2e2 z&p7aTIf1&4CQz+7fqI(S6Qm4$AxO?4`57W3rFOS*HV)~ZrJ|PqIXH##uMY}nLjli` z0Hh3T50b|s`FSF5XZagY{tGPsMNj@LDgTC`fOZt{5(z-cz>PujI3&MJWTd1(=r2%c zQ0JS1fjThID-;MR12+fBok)I_$TzdjdDQte*7@}kHn}AzV7w zL$G^)C$n72&@z{C9-^fvFDX|H*Sp zlg8hpP}aWygF<#Q^ByT=KnaNfU?_wGKsAICNi(1ztA-dI9s}VZtAPX)af4wbM}p)i zlK(-HkfJ8@u@L2j)N3^A6%TP5%Q&*~kkqR}N~q zhGfKTA&j_Hrdw4`hj^PIUTYXcGnfMccJr@dH@^*^wY#;!Ho$uG$Y*g0h@j3Y8o}&9 z(%@K>>EnvJ%SV+owDEDx9YBe#Fs0ZIW7Rr1>z2f!Ry!ck9Vgrl;dTmlyl@W|?gZf; zBHS+FPDB^>8tA-S3)*xN*)-gLC}q12W;qPaayUF_4`DLmjXoszPms2WDsv$Gff#;D zi0jZ)=0gXCOhX|@U^Yyb*>EIf!we+Mq-;P6Y*Zv6mRTqn<)(sXv%(cdg*kwhVHTPX z^cS8VLo2|N_&9XJ{o~PrQ)35{8}9F*9PXb$UZejIa?SoOawGi{$>k05{-ZG2W^1jg z_AyB4Zoo6s(P#$B3^A7(HWz#+eoZzCB8*fz|$2)ssx)+D+^8v=maDNQU2l=7P$#4-0;sV1MEjXb66ae_Qn_pJr2TP0QM%r z)rP$gQFW;@QmDp|l!Rd)50r!vPw1&`T&9k~YWwX%&Iy>}46QeGf^Heq&Hj=Glux5p z*-AJ~9O6xfqcK%t*WrEtu7fJ=U#2u1sKn%&;bd^LSa)s(aWU54Q@-_pd=Cj`0yQHh zW*SI^_(A2*^4IWVMoRUg{%Z-98a*E08CV!iPd>IT;1(_9+-mt?s}`bqy@r zEXL}!1Rhya_{vlOmI4q7Q_K)_8A|>xucS zP29emC(bT4fV`Vjcvl1L6(&g)Lf}Ep-$7vAWp!jPropy?Am3)K0>K;|(_+5dj(3d% znbjf6@G_%XrChZSi{gs%#9>HNDStg3Cw?7IAKNcS6l2mKLkPYOU^+JSUGlsLp0GUz z1k~v0Lp|9WPUtx^5uW&P2$PT-6}8_0s@)NV$8SQ&Ao(GI&44W^f2zOy315w&3I!8J zLSKjL1&J^@6>Pe$V?$Eg)(sV5`)4r#%3Z}qLo|M!*UbPUN~(vcG3}%Ru|={qiHLm! zg3*MTh}vBMwg8H%^jkaM!p*SA`f(T}mWZ{Qi5QoVfL-FQ$uog-O%W>1va9|Mg9 zXR{E06qI=yl*uIuqRj?PRvn^hKIyT4?b*YtxRd;qVcK|ph~p~k_Z#M?2}X8`8`EztQ}s}X8*99>i@fWu)A zzQOR|lT8nP*awe^NVvn<4zQYE&Vl3 zoE(c|#Q~hftONQWQhna};BC4EOd|IQo6BjR(CH+%&Y4E;aAzL5_0GxUHaMq|JHk1a z+>y>D#TSQ0o$0vQQpCD1B?oCMk=FjfNX5*R0e z4heKhV7vqlmcRrF93p`(2~3p0BnccUfy11~IHiY6%w*^1jF}=aQzbA>0!K(-x&)4t zzzhk@l)x+r93_FHB`{k8pOU~F2^=GVxe}Nsf%y_RRsstoaGV4dO5k`2oFIWuOQ2f< zJrYo|Ru_)>(IGrSq$wG3}T zcoV~05x$J!Z3u5?_%ej=WcYG~A7Jz9# zBfJCQ!DI2rax7~NAYfci*<&3`J5`J_ejbNzxEFfA+h}KmurQ*18oI>+>_cElV3~WG z`raxCp2YQ#1+p*Fs84Rk`Ne4<1z%CL&Vmj|%(womIZt4q6rEafUPQPKVIIxeolzLH zRH{0AHER&NI`CTO001%jLX$eGy*|X}BI(^_7$f0$P_z0eoRtTsHKnf~2}1-pTT`x? z_Hh`^=`=raehtD1hAuy8olC=5BWF7A13nveK9b}N&UJ8v+JW*}(+Qwy7~Teq*=yq9 zJp;$R*>g<$OdRt@Xk1es6@yebXdX%E)&|t(cq13roKM`C`_Odu1vpr%(W3S!9Jmfb zU~3Bwuo4pWltgLH-#o2B=qA7=VKrK-=LlE48(;u^BnN|y8R3Y%hijh z2XSZ?he^QzNWvhgj85un_5o4x-bW9F>y+;|#PT-gY%;EvCCjr1N22zc5FfNkFYeS+ z@ob~nT5W)8YjKG0z@sG@&qe{mo@lDOJQ^WM9glkRaE#{!aK{(KqvC6nBTI~h+6C1c(M^A$`HM0X>ufwaU{5}x5v#=iZ2co;9!dHl?WC*ZQWcj7?!CR zT0*s77U&rPG>x=l#*Au(rcSg(xEOv|1g8pjwiuRru(p22Cezp|XrkP-QtZAuJ0lQ4BF!OOLkC3gLnh zCC5%HqUI5SIr~vqIdC9gZQ&T^BCCZ1&NXy2sIl-vWH@&N z+wojhqXs$S^nnDOP8l}m^p@Ie7;1?)`6r43l?7l{4x!1lTL$d$*i26dv)pE$8^;W< zVNBT$G>X)U7}Ny9Wdd4QB;7s_+p+_7U_gixff>tUtn++Kr)hg(I^V~1^WK;)@G-rz zH>QhyOjSXhvU*`+;;LqHI7*c)iJpWH_ZH11KBj-Fdttf|nOxsF-d=w<)YYzF-&5yl z#k~v_v6zn|Rm8ECi@CuaqcvTZUE%*Pj*B!e4h`E{Wg^6}FA3|Wz^p%}Ndb4e0>t`d z6w2cykRf{aC{EWeLR0NiXg?~xucT2M6^Aka@s)`>eqIdM?yjbFt6b9g4pf+k(@+f+ zZ%IfVkB!ozhe>N5HM(z1p*d;bEbOy2?!}`#(#iQo0verjE$-uCJ(7k&**Nz1DH^7< zXmW7k^_};FdnnlDe_@89CL^GJwgjKsG?~TCzncbcKjV3D4}&!L;@?+tsDDVs?1K~> ze62QV5pBmYfW&i?=R#;oa5;E3fQOf`^r+Pbo}3ON#keyOl;(^Kj?1)Y$*p<`Lzn%$&_Em)`*0rAjguFA8F2yvY=rhy5N}gm0bz8VtKUHi26+U z=^8TO$x^aAmaSE?QMH9AbXggLP1zsBL`~E zmjM)nef8p{O0uXBfsB~+!tOnL+!77714^{M&k_x5vLmRVQGxCRQ_l)9EZ;Lc2K-a8 ztrk^28S6R-P?|x5`M60dl3*&DW}4TN+%66C%o@O9{uF)dWDngVvg zwn9o&!9bp_@8Z2F#M=sHtChTFS){4bgkgVur0Huoes7C3?KHq`VSHO-wmH&tAB^>S zQWL5pO?!3&E*5F}+aAEw9UK*LWtW&u__}&W#B9>Q9XHi%iZ`*p65Mg^W|JlSZRl?@ zo0bUw3iMZ*O}*$(m`ygg?XF-`HOW@Kq)+)NWDVQU>j#(1wQuLOTA8uVn*eI*vgPT@ z#TJ?ZLb&M0lGyr^SRamdQ#Gxy8HSf!cp16}vaWDVU^uP`oG4zD*7JjyDOZNPcOoq; zJJ{}7j{uey2|i1U1W#a>e=qN7X~X1>7L8A)La{i4+R8^UulrEEeI@kJ;|%KzoOhQ$;c3|k)nX9Pqz%Z<>NT6--dHeOp6;2zl-$}rT> z*6f@C;n-JW;2z#XkSSg*l+E^oG(dnlRUNi3Kvm{Ihw)RKUyhIDjQoYPZXi(hMOef~ zINL$8L=D1&1hR_I9ffrZ^Pp=fysj_oaTU%=V2|~Oh(8+e&f6$L_XR{-4uJiqhJiw_irLO1G{-{4m|R7Tt2WE-)I`1;U2?IAA#p92voV#jAN7_Ogfh91Up! zxDJ505Ma{wk614n#C@AWT^idCaKcGxR_M+BR`t>%~qBEdm3?a7tOjWBk48I2Zet zaA8q0xpY{!P!UlhtSOEvK-XMKMhzoD(5wT`;(zxhRc!ZlHmIag(fostW=p;V^8Hfs z4Rk|c3Gi{75`j846YE%@T%%6ThVn^qUkOUVQ2ZB6c;8Q&iG1`^CzI-X5+iLE? zZpa$IBg*b5aRys+Mj_h>WV1%X6AmM7`w-u2pk~j=T<;g8JBJ|L=o6}2+j$*RqXnf| zKAD9fbZ>JTVi6ID{F?yzca)cZzGf^gYEond9>hW09xr~4@H+&4Pr>gj;obtjt{-6s z>Kk)wNm{_*x@!*i2*UV+P!}M48wlGj^@7#=sa_s>3=PE4OvR#H7j-v^r9%db3eFLd zlQLDZCUieOHJGHXxXqZXDXic&*Is&in{=;SE;0>KGnq+mJo^8ec;xWPA`A{IH z;Skf<;a>0useaK!w?-HJ#%J*~i%wHrI4wsr-Gp8^)ireM2V}rz-}wsB;g+chI1Xdo zj3byB!ITRLgU=F}1-1(2rH|+@J&8a+(T#ijUcSie5!R^YGRSl2tvu*E+fB5paiIuy z;$WAzT^6c)m5^U^AP%|0Th}wA5~5uLzf0jaRk+=v3QeY};{Cb>&l;cGwH+RsbEvyq zXQo7x<&5=kNya%V>tXQa>pV1EpEb5&7F>pfH4QBQ)k4Bwj`%AO--P(h5`QIS8RADF zeyhY^h4{}Qel+5@P?UE1l)IoBe- z9PvWVu72m&V8)a4@nuP3C4xN)a^RbscG;6vQf8T9{5AI>_>V;%*E)>gx~34 zpgjDVcrzk|XB@lTbF0_UF+G*dk#;uw6)2Les@CUm_O(C043?3rA#PZU_8^Lx3>3{4)i^^; z2_EHq53H>@@50kJZu1RI?0dk^$#kM4_FIIacvg~XY1wMUI38GMs==dj@=WLR^1U)= z6Nt5M!9tR7E&y2dPd}V{U1~dT*QLfCsHSKFo^J2xk>JGkxg`QWP#Cxl0@umFBLEbE zi(`ftF`K>wI`RU^t=O^dI-te*UIAN+v!?)q??Y1^`GQjWHKiJDK=8v#HP;cInU?I*>dE|5(o=CU9 z2v3+rtOXXv`vf-IU&6ua4xrgPFyXgj!Ugt$05;CZwBkpW8O~E9#i~+zzV&4+eN%OX z&b*qiu_%+$1S7sXka#ve?u5s{37{wMq+Y$KMo+@IXXkGt1^+}mxDiQmZsppvVcAfs z#)zcq?7IR&BJ~3E6*~QzK5S9K?5>FIT2wr2ORiLwjm;m_p%F*74E&85&e97(L|44fon>0k9538$|6^a7HQ7 zGcWx;%$Yk908)e?GkbzG_Qd0KUASrv%(Ock% z;c19rX5{*EIQVcE@^&fiaR)f4^EQoR?}a!QxaTP97ReJENjS05bqNjve1|rsb$pg+8IEUgu(4xQfH{kob|gK|hW4m;`~re5?M_eY`8oUP((41Y z7;GL>@l+Wd1L2saoB_2?o&>?M%4+eQ0Owy2Z~zbL=D!ZaL2NRe(M8< z9QRVIQ>9_aU=qAGDc!r426PPY|5K&dKbY z#Li-Nmawywon`DSM`vb(_i}#zAsj@_9A1cNsjpQD!dKu{h-=zb3U?K{j{7dz3ci&T zsqiit66v=2796&JU#=^txJIcQ2lZRryMUp(0fM)%XrqqBQ+;bKXAj-OkPRh)izCHz ze)r=WRdP-KC7vrJSR9;gii?G}3iw6DV%$`**>ei~R)~{NYsA7)b^{%+%D`L~pJVBH z6I52#!1-#ESWU<{-zbTF1VB%@ZvoCveXa@R{f3_ED16q_vyGld!BgFcn(uvWM^z5z zJ~Khr{cDs^PHv~AkvgmtPs)dBqzf38m9ic{J(AL1UlEyHR~yXlK`c9|LL`=}WFZpE z+=xOXmbsCINGySkg-9%q>1ZK#8De9F*yUW_@;hR5GliD_VvGyqXXH0R5Rhq`EAKPz zI~B07l(KP@+V75J9NB}QASTcIhkZ>sc5Ag!{6z}ontd|u$bCb8Hz8LdoV-w(;QXb5fOmsW=EuaLg*8|Y`xfv7 zmu9UEwO-wF}icUK78^3?)(TmK7mIHFV^u<1lS(s>t}@5+ikStz_Z)9AN%L;ViR^C z=!1IF_iYvxrSXnY07uw{hmZ|*dpfxATG$M>;z?x1+3ua&Q}!oE59hl`QiTvzQBu}^ zbg~Gxb3@Q+Z*tyLyz((|NC1&QZohJJ;%<1lwvVz+x2nkvTeTuP7m~Yio$s3wMPcLr zQCOY6k#OR^^tVFxfir?5fz!CjIh{uWXNU_<5o>>sU!L|n z&G0((`?&dGeE?5xB`yxo^{}6VnvQ)*cxylOxA#MTXFv3J_d|crcUB-N_QQPKwD0w2 z;E`=weF+}xGGx%~D+FJI_{Pmiw1;qnLVE~Df)m#{ZYo%s?-I|B=qa@ zELVjxYAjp}3x9JtVvPgmKScEzCuD1Ya~tFDi+PStdwnNkJMyr&$KVm{Z=nAF0Nnhe z@PLAXA>nQVB=tWA4=e}h+K;2>DxasB?@}u+4A&Pil`0YYmG#z8nBE==(>p_9dUq&H z@5z1B261186`(eCYx{x2!O)EHHDKF0&N#OyWeAGHx@;;$Lu9SvpJel5_|{ybfhycXs3ufulca`;-^6$z=C3N(}$!-2~^i! zv^}LLpmlUHemvr5?=2#Yilo|ysPnLZ0hd--OgmKmDpy`yy?CCS?I3`N^Cdz8Al>WN zckv5439WAc=PLD@*4GaJm0>N}KY$Jw9gV(=RoAW2SG3ymsYC>D4q``MK_*$bHSF&Wr zV{jFvJA!kD^%-1-6S|)OY@Jv!I-?>{c%d)W=`Q@#rk8$`lb_*mF%&-z#UoNnQAm+8 z!H7281TvPAjP*1#6($-NfzSt|t=;68MIia&OL=DsTlJ1tjSN_+cX4cFyd)`Z$&V?LE+;O5#G!g zBVjfO;eWy5`TL8o7`@z0OM^cthwLROUaoUO78j->nB8#`vpe2(KX^=J2j9L!lmS}> z2032_0q=goM1gM@FlCRW00f(R36UNFL{37-Xn5hTR@luo6fNX7biBuQGG%}8T~T)g zd!ZEsx-i|B`qEv<6BQ}Vt`f=gSc(!h-Ip-IQ<#*p;-t_rx-TiaIHMc=89k9QS`e%s z;T-M9@Hj(SufBVsdyZ>`mwssm;ku>IXk50$Ojj*i5=qxBTatOTM2v@)j!{O~2oVaK zuK{eo`(2k3fo0<`Jc2*86QU*=L)2pSUbM{5eAQp>Juf0{hgz zvAYtkj5g}6ry&HEgz8YldIn&T@&!~9>O0<}m~)0{wSqv?%1PNYmZbX;PsRB}a;#yk zqJvzl8!Ob)K30CIl@U5=7>Agx=TOz>ec7mYFQiumt*MwKzRPGHv^Spt`G}qgXpMU_ z2S8lweSt3}Qu%A5QDB;b9YBgBjYBAt<2eS3tTKZswNX~DUv5RTAX%d=w6rzqYGkz zhvI{6-S(Sw7Gor9;2q$XQAjL1x;ke40>OA9o`h{+GZBXv@FT_ycGsA|@d}#fMYu`^ zu8uyzy-FtG-iuxt8ap{uA>YNh3fy=gFQwHB^0dsCW0?RcV4woaz@``zyZ6Nf>wsbe z@pBDeVi9FGf%Oy3NYaF$Fded`W96fmjt zmwMmP`p$LJ*sVkDI|pmuC{<&K$vwgb)-;TBCGCj1eQwcy~KvBs6O49=Vm zTL@(^5zbZu@^viTdQW~QHU})atUAQJ@oJ5EquC0;A!~#=q0WmAN8gGr-(k?Zx{y1Lh9@~$ph(a9wkS~M0+ij!gXXva z4h80_wbnD3i0iA|8#~E!7%B^U_ePm8T5_LID5QQ zsr>y*A?V@UQ5Vwqp{yp#2&i zot5lS?YEFKI~J(S{kEXKNz`{JY*59ybO+@ycsAGQxjUlU-ouX;94V+->=5fX{J@2P zp;dDGT@sXL%zNOe4%31$Fp`I3`tMB|iRRx239@ZoE!x1LSkf~d`@LyfERfSiJ%3vB z1b7sxBI0$=eEw(g!mTQwbA@XAiU!Ue(bn&o^lgO^bPGUh#Gu_*Bjd}0T$6Lw7&tUT zFDlv};MVS?W5m|3sNX(rx<6F&A$T3OI>3{GhxaXw`AW@lx)NWRtdhmxZIu<&2_3I6ZSfMJKz}?b4M_ErV6Z;5JrrfIWw969m+C!=2;1AB*+R1oPvg60cLmE-b6IE z1%h}zT{#Dh6w#v`q4c_U>*W2m7J3!iI4N!0NT!{zFVnslAsJkT>AlW%9LLFGj`I5u zeQYqqLmD#!s6Sw(-zo2%co4#@FJapohGg4FvN!)pY2z;a&yBlO7+v#i(V7nyJ$Jb8zQO{!bx1c2bNHWeyMMoBARbqOgj=wL%5ODe+hVm9K0^>T$EEwSlBQ5GcG!GBJ>wA_&yp+ z%y}=+_8EP)*0NC& zx|ewU*rBprcjtH-&qP!%QQcJ`mF8@)6+KQ4V>I4cu{Nlml&)f$5ato#t4lD%3 zF>SYwcTH^x%+$wZSX7r8cQmqvn z3&k!EIOxy9{pEWxpRT#PKLX5^tDfC+PqM^ZATn!1u}Wv7181E(qNd)r2|Qr9GwBd3 z&odr}^z;omJ)B)sQe%5do6%ZtFdr4)B&sit3uQx`a1N4$7X!B+AZJm!5blTDJ95YTsr=(bF1>s4lf{3!%2ST=2Q8t%#zh)sCoYwQn1u=xL1u z6zzAYkaqq{XVYUBsT@@Ykh{^#(R8}rEdeTvA1}Qu`e5{mcR^tAiQf)Lu-Mkg?ArgN z>(NtCbpJ)yqeG4P9_E>8eU;B0?Z(pj248)?++D>2ZAc2c_8yuxrQoofqQb;Q*BV$# z)cOWEfDWlF1>dA!>65YrrA!6a(`C5OrACKM9To$H`);2$yNb2higKp0YpW`R4uhbu zr6C9_Xmvu6Vcicd5OkFV;mf$E`UGu5K{MF3!x-Akj;uB<13+CH&SLCs_|)pj2SgKv zy$Zt2-O1IyOQSZQoQ2*kapJLYDm{668o=pBcMwN`$gaCgZ4K4Ec2W`t0YpHUWSq^$Kt zNReq-H^dfFLx$+J))iqz{>&3WL^j0)(aW^*Y)!Ssd8Qk9VsX0N*~iOhw6nGNt6OKkIOf*228VDvd|WJbGJc3d=m25^7qE zF!w3zjLF1Y`0dFBeNM!?RT!Rlm^kznHA@mlPdkdqtBARP-7oxW^dK;p-W=}*k zLMj}WXob(KmO(n`QxUnCmM;fSm4c%>y8=Kpvp{NQO_EA6ax)Z`_R?wYCvW7`aMjnX8Zmgrbh4i zZh~+u(XLUk4QVj!S^)4I_b_n5NrD5P%vRkmWbX`oAzN|3RdHaa5|gs0gFDD|&yya{ zjx<3!e_DXWt0dkY#6l(Sm3l337piw=>!3qC`J2E!&)3&Ld(9Ea_);L&fG2+oHK4>e zsRYGNUqP)?!oy5B!Ne2vsiRpxB?l_sm}GaPV}9OVpneWS`r21)a%;QRC$}axoc^f%EdUBK1%_D4ne;3`g@D zar^%Y8tE~s^;uqF?#J*V^cF2w<;-eU);Pz*Bj1a?z7VF{!>Nc0Jst-40{45y&AjU6 zUpEfJuM>WAc%u_PI7|h%3qnCDt;5NbYFJl-8?i4yRq&I?BXBw=&{6wBiEaR(Mi+S4 z;<`u@Mj;_A31RzUCge9G-q7$?gW~{{4DfAWW=LkN)i{uvtwCP!-GtUv0OUS~1j=tc zUs&+1=WD>--?yHBt62$^ZV0A{lIC0a%s_=F#i+tlY;orc&F->!M%JTE7;o!j&0kGN zh-#{e3M#6r^?B9%rp)UlzbONg8c~l{LE$LS;#w*LnO&vwU9+}eN~!?3lDhKqXm<=u zCCU!9VQMW~yIEynI7m!F7X$Tbgj|K%cP$n2 z>)_dwaqe*i(3;V$@?GN6vRcRc2sUE;{(ETLPm=9bAQH~yTt^kri@$Z6&m&mtRhL!u zQImE95YBsv4^NK3Uf^1kmamIJ5fS^J7yrNY&F)iQaLAe>pH}JWS_Jy9=F^Fj@JQD+ z;&dWKmtO<%5E&5n0m8>ad-HC3kcY);8?PZ4IaT(MPRwK7LR;+DxCqZwj1`IEdCI4x ze4nCz`TG~-Q^2}ar6a?{t#U}~$0cw-DS`W03EWd9a8H-OJyQbrYzf@YOW>Z9M+W~a zfxndCdZ`5NMBIV^PPg7G!T5d&+y|use~8Evg2=G- z5n@j%z*gwi$B185fTs`L{a&ntc@%30qB?}byzf%ws{}hag;}Zo(jw zuw5OAZThc#X9ec)W#kEN47f7()OU2M4AxtX*gY6@+(ox0!&97tF|1ZPSaY3wumCnD}sL%-}>CDY6>n#v~{#1d#uE0Os=jRXg{4xlgqQkNV`gV!s zvR)s@uUzO2geC(-p8`s;Jkbu`3GPLZ2L4b~I@3NSV5L+K6NWG9XhA!82j<|l4pNWX z1Bm5Ckow$$3>~V_ZCl~bAy6Rv_~EAge`+I!VFJNx0baZJ*vZ zfqOBnLp5P`Pr>)vDiw}`w(=<>U~wOZH?hXfmEro1rG_;XkmVeEeGl9P5wXT#@M(aK zM(P%MKI;g4ynrLC`tIhkgg);1>?l9G;j&K$-_g(U8LDu{Ytl^N?uDZ5TpKvob+D>E zw?Io*t$@|ZlyxKo_WX4P{^8P}A+VTr@1g*b<$pL2B@;e-qOA-vD6AJ}&cs_H;XnfC z7J5dY=Uul1?Q)@~y;9|sG`H$~0uV4u?;p|oOHYa~|L&0Ik7y%fd@tu57nHFlsc1y+ zfD9Eh9TKFcH%&OO6cGrENz#(%7U&~aRH@mzy~*&$)baH!d@|b?nCb=z0OY}M{hPKc z0k5jK!pVE#C4>hgF=iv=0Vep!O9F(&NE88)O~hSU1O(J73J-3eZt#pF4%LYQ5s8m?t`)Z)I&S&%p1jFE3r zC&PmRa54ao2*7Oy*1DRE9)l7c#d}iMQKp>YKScVooDjjNn1XMnb|fQ$v9zC|@CVs* zO@H&wVpIQ!5r)C=%!8MXv{sWqf~hD@O>(Hj`$u9$^3GDJ!+9cTR_>h8SvKjI`O znk007ZUzAaWmcGXp~LF{<+a3q133A?|CigG=-45Rn|9s^0%Gb7RW6Ps5=#~tXdi-F zl4L}RJ9(08%s5^r&-XgFB|m}t4&bZb={Y2yQc*tnc?_{ssmWYMdAM)&BU^&M0s1AwZAt#jRi)Q9jKeB#lZ4e?QzM5p-t`n0h!s(nYnF!_# zluO_%SU8tPs2D+Vg~ONF|CJK#|MQ)fxLH=pbJEpLQj(Ld*1JTcxv{9ecjUjfk2^6U zybu~m=2Ln!&A+&MiIO78s37^5H``)@6#fjCTk`ZBn}f`lsw@U6d~>y53^A-x7K5O8 zS&|gBNgzvD00zsgrW>NTvqmH7uE6~QN18SSYb%c?ijxm;rvo;*iQqt;oS_UE1dE+1 zQ*+!jEPby3e&k`MO%+a?N@A6U{K>pmGCSBRNd)QBBr()3?1IFw@9OIzzcHHjYamvP zA|epKQkMiFUO+z)M-yGzUqn*N^Rx~7ne$w!wpgOLr8<@lmgHryr%8B9W zlssQ$Q@t!TqZ5{1n)|Qpi7tydwI3`8JC)S3vvH)ATMuK@|z=i8NBxCqiS`i zkHAoOGj>u&HYc+su{unJZOdXw9Dv$jWMKMm{j<^jAA@(39Pmx~>`kwOGrpoRL^K*Z zlQEV2X|pR>qPz0A{=mJ4V7o8sjvZK1#kckPb5Dvy86%hUrVF_6^2~>FL)5)|14UDW z+S5!wotMMbUCTk9*x^n2X0N?pLZ^R{$6a903}}MD97MeiNSBE zNIn#mZ&)V}D4?*syjmxK3H}67O*sZ?bDkfC=Daov&G~Q?no}?u%_$#^=8PDP=8PY0 zCkm;kd!kQxOfJGRM}zRv(I9-TA-oZUslwcZtGXxogbyXcRoR5QM}O6nbuHBRGfY{P z(d;R!hP%M0X3DyrXP}N2N?CiOfWsNw$RIM@D%cT>-AthS9>+PpO|Ff~49DbzCc#WE zJyIwG!Bo?&LLUgGO%(`yI|a?r@>Cyy>BouST7o!@D^8CR7J#^m3*H6zI)CycNG8vL zQB0oKhbK=)ang+@+-SmE!&wO>Nw@3iVFCoP*@Sm#0s)wIrIV$icFwvv*Swn$+m;B< zyI{zOY&12L^MgAhwlRuK?k2@|bEoYFLGmxn(8vi!jqt|$#gmege_J>%;)4+F+%C`j zXPdb_5t!Q%)2SL<+t@}M1Dje5F_Q#|3bw%^w%Ha3n@yE50dQ&cVI*9WOk9Hm0X?`5 zm~$WY`)DGk-;hwh!6+ef1C!i?1ZEVFxtS4dj6ge-#1JL1o034=IIU6BL?@diZL?6@ z#MJhT4K}+@$I$&M0q7iG5)zy?bL;f1|LykX`aQq=@%pm%42FKo1oii}T z69U7*7L`WSb4N!D>d}(sK9P<`IcX^U1jkJJ_w?h8mwkjPw?qg^lZJ67XTWrc)p1-f zwCk_N2W#slAeN{ZQ_8;BWcI}lplHjy)Zkd6aZEgx7}Bzspq3L;C9y8K@L=?n5+$|z9 zu}) zkihpdd_Q0&NK^%Wh~b9-Z}+FQ?La)riH`!l$Df@DlG$lbGdpbwPdSX@r2E22gp#ED zb7=rEFbOdv zf#s&s7yy2yX}<^(COTy%2FvV=G5~Cu7~0}zn}Vqf0KL=WOl4>i(I%kBsZ8w3OMbs? z&oP$)i;2j#)p-WqTQi`coK}T2Ad+`T+QgjG+(cV=UsE`VG$2qIip)G>C(SADGzSEx zIkY}5p`GTWt#=0IxpsGwYImN+_YNi^s)?qR1+glIC%PFYIvMxXjH*Ah0MjH`=3;>NpqAOGVw%rd7Sd$a zvJAE8OvYg9SWHO}Lh4A3jpx{OiVcjIHmBM(Z4$?tHElA-5>98E=*(18gEQ51o~brv zK9B(>spr3tNr)i{WC=^aH(T?YlhfYKu@-4w4tobIGN9%-g*~kK&2cTn9LGY; za}(#;M5kRnuldb!MzB;c7vgskg!ob1g&a+ENr(B`YkrU0QOBUJ`Ju{GTw_PMYktc! z|CVv`2#=F#JWi(bIC%`i;x`=d+R%?pyK4QFiP2b@IBX1-Jf4!U+M6~OOCAqPIKbO$ zkDk}+C;JN@OM?p^3-$o{=nLi zf#b&pkW-$2#m88I-7!~r$fwBJm_@@-f4mR5Xp2WJL7AG&T&F`C8Vo35M`}9 zg6=bHB>>$ut@R>#AtM26LG?XV&c!>T%h>M*QoIMxvyRu9mM+u*##qtCjVKR!}R z@Rh$lbvltBQ4$@LKla$|twqs6U;gT{_L0&p_U8#ZIg@_p?z$tNkJfzvSsBS>qVf*# zX?y7Fs7M{udCB^`rOzQ#;+T0$pG_V>G+6#}fATrhmi~FkS%hmq-g(6c=iie!=D9xj zfJ!XAl7qrDw}7@;G2Kk#)#Zw%5s~ck6_K>ZVe)&N=hcY!%pRI2>b>a0$PH~giy~0N zv)`cL^QNG!QFXsi_jTn{F!PEdv8A(1@}e<`&YeRq1XU~@zH78%WND;QQY3-!sVYht zxeJ}4>`y6kG=s&cUAkuF-qT@i>(MSxzXD}koeTiJ}SfUy6 zSpPixk>}(=lsA2FgzqnyI`jJCf ztKRB1RsXDD@2E_E-}eIw>^^PVsmyhR61nAAUSe)Hf6pn1h*dEOmu%Isl2vyIU~ ze~;!#PJxi~o?JO2{qw#1b0pAw@`=nRkMewSIL{|X@O<(Vto8FcpLp4OzK^uQ;P1UB z=97CQtoBBZllf$)^T-r`9yy1^QJ!;B9Co^- z9gg|?cB)MCB-d#&Y+3Ugq|pC}LVv{yJ(3kVn-%&3Wcd;YdDuTXBU`68kAqGd+M&~{ zB&_zT_kvC@+N)=sPV;qoC3kcs+jsA;@(Er7Q!hioSA-ONRaD-|?U+N+wXa$a{`yGr z8t9sl>A9Lrh(G(vCrFfkEqaM$l};dRUeDMk0-XRE48?i6#v$~Cs=KC<^!r9k3TmIA z0?;f0J@%B#OnsSGI2#@4*P?L>-MP70`;FFxGV|r(*R9ZYrMsysxouj&bvO;`f|zXI zLVbJayxPeAYB|biUt=&;>M*~M2>Vm%lVXqMUD)&39%pt$`4~gx(99RoEuZFYc{ERP zot%=KE?<9WZtgfSpKx9^^_2*HBIfjb%C?v-@eIn4Jcgkk5e{ZJ+B917_bK!S?rlE3 zo?J=Eg%SBiQ~GRz<%9W1D?~BxWXc>1e3N8sBzc{f-dsE=qqZlBcK4)@PkE(|36K=ACpZ&IwT;oWXlD zoZQjC#&@ys-zSnjUe2Q)+&g`O9!KSGZR4xh!@OSO?F?92pf_+~*B&=;;g*O(VYRfE zBnZR3!SK&tF7DkF>kWqOnXAEh^E3XrIN7WJiS+%{_(&|hLX=J)%qlFT?`6>dEu^no z4UU=5AI=$GA+Im25P8!lvw9UJPGgsiki{lb>y}F29y{*=IGg{G0#zT)=a* zv?P6`oY5|iiCX!U^Lq)~Tu>2zxgv&^y%s#MRoPe+I9oZWiQ4vc>c3b0s9y3;|Akz? z-ve9F1B+wlH*@Rwi(mWj7s(>LM_U-_o!pD{R8U&L$))CF@}wpGVtJoZd_=t@FBL5> z$@9Nmb|1gT&@q)5NbYaHb;RFf)AjjXAownU;eFF+LRk$o_jC0)NDWD652*TLk! z+%wD1{TAi+N94`K zfPD*^cn1Ua+0cOflW}I3v$y)b5EYUAB|Jo5 zmLbZ&=@shC3O!K85DodVQci~@<;OrEpl4qe{6sVFakiC_JS`eWnA?{{A(Zjp%eoc1 zzAUmEA$4#aPJ6mUN?*g5eb|S`$66`&F~|PRv3iPq!d$(? zsQ)mklu(~Cs=Rps81?MZ2s+Lm9S51JgA7~W} zAajkAc|c2~T*>oz;_opaU$iMYAeCR?)%ID&hDD5Rr1ugh4Bo>&vL= zqu1x!3u2W*vD}hmcW-tIS+me@`V@Z`o)t`Lc6W_f&(L;@#97nOw|xaI$+{+uyU5Sc z_q3$wAH6^_nR#p*@p}p8b@YQ#l`&x&uY=9Bd+0{>qjre}8j(IVV$-Te^^2hyPLY~X zr7>;@mdp1G6c``{KFKanE9g%xItDza{|knNfSv8*NBnovv}J)s_V;veTw6s>NU0{u zxVy;Am9FZhm{C~dQ!Sj&m6n)s2L+5}e(;rGp+F!qnFeU|m> z#aZZoF#QiVw^uKre|hQ3F@UQa19+Tc0B1V}a0a;MSFK)96BryQ={LkoaublNOs!&Y z5h(Ei)+Aa%ie7mKfABm)|&B!ta~$ zeGs6m6BdJQ>luxGbb0CyTG~{GQYs?a{1xI$YV#M%_PjR#Flluk)ndFblJr|0EtHqd zB88Y2hDp=os@Hf?B#hSlfT_MtyIY#b4rC{B)kh*YFJe0cPmW z%?urSm7t^m4%=Gx$nx@o4qI7)%#DmpXEd1*U-*+HK{8qHLOChqtg!v!S5_8eIc&&a zD4wCVUFd--jBm(aLjl+`%8ubhz)t)%)Ry^@vvo%Dv}hb*ZhsAhQ07eW*W3zSf6Zx; zXer_}r%QzNHT<r1 zCz`O6a!{AZXJzH(+(%zI4Nn(uOIYO{I~`9Kf0nSun==DX7f;XVc|G6||M6mI!8h7R zXWod#NWS#i`hx7ojNJ>|ee_}Is=X-xTK*xpkl{kW(R}T(1WAu=1OYCAZF2?~QK*PQ z?aR`Lkp-cB^d>?@)BFqXqebE^8kb5@b?$w1rXbtp47mH~El2=h_tBZAbVUZf(LTD= z!L*?n{%u#b-F;s|r^qk}R{f`IHkdW*per2FV@3!KRjbnzE0Pfq9J`Hhe- zu>c_13>hm*>ewSt_tH_B?xjmL&R+UW(Tdi3?3a(=z4YG8 z&wiix)k`9S&zSh(m;B_iBZ3QQb%*&7-C!jrOBXTz`XUEQe@+=;# zQzFUngvk7W4b|BZ{U+&L`!2u_30c`v;+?gB-U@HvOrrmz2+^mMb12l81f1yn6B5VF z?bE@-z9BX^@81`k+>hwZNjEd1FwMGZ97`q6r4q1z+^z{b+pFizcz+unyYi?b0?JWP z=DnZuiPojE7cY`&I#9$xgE(R&A$#);x;5WGd)C8e>elpm{?>FuRCeJTyd{(fRMsZ^ z2{U)P3I8!=34VY60CyZUPYN2V*4AKb#E_ujYAp-Kcdf*q|gxi4pYIMYWaxxexxcRu%>AM+%~ zGs2)vg?V|El@%2gl^s7}WD#bIz7&vd`sWRanzg}topDAVfEnjj39G#1EKF$EN?7C7 z9*7C;5(#U)l7p}|_#+AHyn=(x+F%AivG)mpKAv}oSsVNZfWF>whnls)zX0g(%{|PV z8GHsnsWz1U50nc3Be?hb#ca zafagahGJd{6sHNk)>|OqKvQF#chUmYE(7IN+Nh!VrarEGcRvzXKRwdt=seTEm+e%$1k|GAnS}~&({j{#h@vLi*-QA#X6`U zaK5FSaz#2W;D>-p0p~DSBj9ib2j*v;Z#l#FJr03y#w3Ie!Av84p-=;&h7ogxCJ;<7 z-71uUNaUNtnE-J(Gl8_hOnNZjGT+rJGp^pDaP^3R&>j$@IH}TvH6|Qr!h|}534<7{ zh{5U|N+(}f;O`?|l53soaIvZMYgeyOsS(9R=2-|Fh&b%)8DNJ+;+#vFD>UghxUO}S zAo&+QXql8O%kn`l_Rm&=HQld5Ox;RwXk#@_Y@m%nPEvlZEe~dzDq{e`2Pn%>h=85@ zvQhs$5c3$`90L|hPY`UTf~j6Ck9{?QsLuD_K^Z8B+I*Z3(FWM{C}{|moWMP&jX)X@ zSRX?h;t1V+xT~#?432dl4pCifGVFreb^O4oq6WY7fdb3mxLr`-nF)efU48<4j0dEP zU#`5}_rq^+-e0xc#v_O&kDwo?!(L+L%D;H;#&%Ra?*Sg`g;#srZyr;#{TF8+(QBnj zVS7GjayoDq26c{iWFOSCA-4q2Iu7S|(Ay~5G9}fYkA)n&%45n6L z83~O|9p`i-s=7FJsMC=aGHQa;l_oN(Iow$7PqKz&j)$Oyb}4BJFD3EVoUZ2>{tu7`PN=|UgwX^lVIx`*dX%{!MiiOJK$jq4+ETHI0d+w;by?Y86FOJB*P;C zkM?JT(LgXi#FW5o47UN^&7T2wGc&+4GXpfJ^=5z(yDNeKK@3v_0fI<{CykUzY7Qqg zo221NX1GC&RK!Sw7;VC_VIpHqQd>BwO=lhPguYu~z6%_vInm_NXL^1$*?Q8d7at9Vy0MOlQW^n})(5VnHzs$+OB*Zl7RFGr9 zC3iX}l*ItZ1?qY@6S7ePnILV%G^x``>a6y(j`8qz+S?fS)GnGMD?mEy) zo7Pc~bx^ZI*N7me@IlShIvodPXZLh~MFvRF9?lemQa|0KO+XqD*hNA=%ZxI!I3#In zIz&rkY)zfP40AO@r)DrxjU#mD^S=3ZK2Q5IY&tN*LSn$LbnqQMz9YC6W<|$|h}yGW zC%cI!JBgd0d3E0%k{X zA{Y;*M{y#QRf6*+A_*dpZ^HyR2_lSBd^03C5yWXQMT$FJ)IdLuQNmHwj6+dGaR$th zlOSR^lSw$1sSEQ<_}!=SeB+Dc6F?hWW9n(0aZDdta9l({%d*tId|GuC`y*?4|BJsU zkRn%Q!Wh~ZYctm`OlUuw(N(d;jP`Q{b4Yuagmc?}N+Ebr_l3c>3w6WH$h_@LMHqpn zI?9^P&P7V7fi5UUEWfc6DJ=Jf?-m^NNC%$WqFS3_7D_5{%u#fdyCS^a5F86(u zpTI}qa#EOJE|~tQkN|>)s6CfTxCnIeNQQ}~$@SWFBMT4p@cyo%&w1eTeolMlFcrob-q2q~;OcNGAExfKk@DRlQ( z&I>$0UKF&V-S|#I&9ZYu~evhs>YUAdFtdnVinog+Z6S*Ls6K8?F=kSvDrl z&xVZzwTw#j=cmJc*cKnaR|cE_ifUIGOf7;rLz_~EIz8c9JOgT9u+M;@7NJ9gp8+om z+Q<1nvx& zVJ+o>?z7xPe@xs6JIPrkKfyB@o(cFs-$Wh=#5CXZ5hSMXCS&?$giRl#IBBL@wwVTT zpjtRt5#7WTa1KA0ecLFVWTX2~ajPKdR}2&=f?aFcgjr_UdFS9LqMt7|3#8R%Nz7WH zTjB8&01IS1{urv#Y(kt06YzD`x0d*F-TU}2b2>8orY-W}*OUgx@L-)>s z#R2=WF=$^9Rr>)4Eqj?It?Z}HV8IH~M5`f(IEp4;ST zuS+^yc&~T9?)4tT+ND?GN@NIwT3eP?SA}#|nDB%lBc?-^1=$+%CxNjt3!J z5pV9;+uwiR2c&fDNleEcm=o;wAogHj8R+>gzKH+59?%Vsvxjw@p)ThtkL^06n;PR1 zy6+(#7#LR%2gennI<7z+`0aK^4z)!Gk2}F(kwvVR3_UJ=cIaXa{%ZUs6&~ zAL)3M5RNjs&{4wAG_!Rq?eE;}aj+dm4BBDz2!>IZ0mu-Opg)XmrdQWWWEg$G!|3Nc zjBemzbPz_(5&nBhpXr&8KDy1daRIiuhAzbZ*wqqNdo@R6qwQh|2YCG!Vdw8`2?u(S z#n|~sx~nx$KVzb&j03ul_A|Ejl(DvZk)LtDo-z*XUhHR_-BZT8?j?T46SFhs z-mp9Z-C;J2=&wvvAcp5xoYImRCT5rsGxj2;0ndZOnSIr(L4 z=ky)*Kgl@aU;B=_P?tKaU5n<8_w5==`DX)Kc8OVH_FeHgI{fGKXv*Horbc$EH|!Kr z@Qyaf#VK^{R3vYN+Nls8Y@qk9}>x<_cU<8N8r<4tsrh1@;(hv4~s_aI2R z$6F}GxzIfpYWI-Q{m)SM_?>9LQv9v(HH#!*d#F&Go<1Yy8R-h{lej=AU0sO%RuU6 zGuT)9!+hHx2trpJw%k&(R;2aDU(* zf*1MyVUg(%U!V}@LVsAI{XvX)q!%UM?YKo>N>}(&pGJhHp}a+(xkm9z{-zIniH8dS z_MK2E2-z>{QTY#}q+R4k94~u%rgsoJX}AZgY9ds6!@qV~^N?YFVoZ)de14YeO*)E;^a z?%T^%d;ead_HVJ;`G??ReYGEJ)Lw!@oC|6v0BV;hdDpPo%b3|T{X*?RQz+};SG`{@ zdglV7cLt#MJB;3sh0qD;S??%m^^UlF-rW$1Q`m#vr2zDfqANx3E(>A3Q *%Iw18 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 z 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

  • +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

    }j5`_hbk`J=^`}wRw#$CT-n-mV8%*{+m z%_z;4?)@0;jwuTO3>UlL8c3)X;M%3Dy-+XW#y8Pd*UH57oeHD~k`cndYVicR%jJaj zBenM7FC;wBq_)3iR|tB%+{lSZdoQF+hzwnGf@yDu=1W1zdTd+<&7nmglu!G;e!`^1 z+4nj3`U+f)Yg>a0%G5eaxKUP`9SS{+;fCz`Ke;m(-E+HmK}R`Th~Tl$*Myiem37j# zWH(4C4NWonUk@cl-vb$VVTzp*+Ufq%3WhRr38vV;l6Y03+C=+oM%6uYNU4 zOgxQkA%^ca8yDW`XHd$&%5f7pi8FNt#mb6T$MaWnd#mTD3#2Q7eNopb3yavcugFDM z7fH$O$~`$U)(}XxV%X_Y%L}LUh!i(i`7+8z)eF=fO_zRS!F8zi>)z*^OQcHu$BhDL z!oD|(lNM{#v}ML|#PpcmqUy2lUWxpHP6&<90b!)iQL+?nS46_t+U31_x){1A&zj?m z2~B>ZEe5a{%BA`RPeq#NOK#{>UEg>yPG}VO=|d4FwYDzR{DNt?GdMh9vji9KV)cO~ z+jlj{mKxM066fWQXL$1HZ!L~n!79_lkd8OILFpyOEx`DKBG+jSv%@NriPkLhswB|e z>1^_ueKt{LQx~ovPxxX+5|?EhwdyJOEw*B?rXA4t`DM zWHhb{JQLIDl+p@1(f6hlft!a;EU?|#4FQw{x(P3wVPS5yb&CaTH2x}g+Zgo+hf^o2 z{S<~1+YAUlXjG0An4gzHVu2WXuw5%@A4hmAwwq6@QCRA3TmAs+KI-{{Yo%e;93&Jj5bamIidGfAzx{GRyF`t zZvIqL&Z;Q7GV^1Cavd265rG%^+$>gKA>RZ;FA0^qLA@T6WqY_A9)1bz*X*Xjn=ZUZyLamsB+8Bx z&o>+;U*ya8xQkshLxfN2yLWlQ$#?Y#Y^t!j><11T^PFu)Fw6m6c|Q8y4y=I81(da*Dw3|>uFL8!FV zs3kPdi|sU20ixG4Dn$@o=HLT`91LU~)|FkVxyr<^v%a(LkA7`7sHw5ct!c#OF+c%B z4MUWckwrJCtQMI?99rRo-0{*Sg=Q;$Ytra!nz02$th1~i+D?qHQzQl79dyHLY%as% z+SvZvHd9J(9<&1UM5jD&+Xzf{Z#ADADXyF4@`IcFh&T(Y>N17nkaEzR&BCpHK5>F~ zFda+bY(RX5Bmk$GW3}*%v4WfVK-wRJf#mZ=Z6cW@>$n}t`)9aGx6(bzX=v*X+8vV6 zTo=I9vE52mks@`qBKF^O|H9z_W?#Y6sCjph%swMdY@Aw0#00k_J z1im+%`(m}8a-ZFea-Ef(3ONi-P>|Pj*P-kpVY!MUw?Kr#FEB@pA-WNR;o*^QAInwVUfMADz99$cM>_7-q$BzjO3{5x z&hylm_=1CBhK}TrTlBm77M%#u|ImAjdJ#(;b35LkP3z9H+g{`|#&f;NK8j_&WQFV@ zIgM9_hIm-Nb9d2j-a@%M_ z;b&h7pXrk(PZF`HR9Cgd7m-)g6Mv+k~&1V$8!4bM6MFI{dxDWtS46p%5 zQ!FIVgyiB|@LTU>nxHjWBKDFz8%3|$!Au-(5B`bOFoUq8U}x>9qnv}s8v7O3@?3DyX*#W@es9zVkvzuEZOdfF#qri&J7IbGI4Q!7iMqYQh0cGq2x#*F*;+Na; zkK*eu@;{7rVJVI*(2eG}0kU0PpcjBSLdQc-^#aMM&md?gkV}(Rmm-KSQ9K%NNoKXg z%1t=B^UbNUM1>u`b~}*@c;(GV45$NhDS88BRq710qhd3j-3JmDf!p7jjO5BYO8v~Z zmw$dCuH9?z&M*3R&Sfbv;J>%f=)0>@fA>S|p`&r_+LDu3Fc9DJR1t`s7{;RHv`<~2 z{?ehinCNn$_%e(opSgh~Dg~qLxc9h#>jcv=sfeV>V4?KUF3DVnz}Y0oq~0YhG7g(I zH8cH$a4Jqv@m}-t$3k>x?tHPZT5>b_XZWW(Z&bmmRA<-a4Ufe?M~`)11lW2&lsN3# z?x8vHMm`~O8;P>+3xhttjYW+S@Wv9sV@4T9g~K7`9S02JX=4%PX>8g5)ly}DH7jRX+|DOgz->)U;D9rA9KKb4_apL+R5A3E;ZS5woVm)I;LeP{bS!LZ5 zCUaPuCP>Zrt0*tEz7kF$>HIG7hR1X9)Ho4^|3w53ADT*^7U#Llk$aGlY$Jun66AZ_ zs%A~ydLg_}V{rRTXuokX@UyW$pW=l+Jfo7L!qap9fj%pCl2He6F!m5I0Tu^G*3)BT z5qR5Kl^B2~6y0O6Ll825I*a{WqnwH+aTz1idTtYH?N>4ubYWDA4b|wwV7RdSGX+9p zk?VbOl z`U3A9lDj|($d?tSu|~xQ1$XP2)QYb0G4fT~=N)-`!S;4kxf{%zCuQSTWmC&9P&nE!r$ zArcj5vI;U=sT#1eW|zWfIen8{v96k)t1!y#;jc7UQcYfnZ94d1YaLT(G^8+>Sb^a5 z?I6ZItXU#02vgcSr3(hjapi!?UB=x8sVjV%tGVlv<1913tHS7Vg(95It75jM57)8} zViy1+Zl}h%G?ryNDd?;9+&6>99hf2kcH`(?s@oV#8+tPsnqJasK0zz5s|jRgSYMeb z3F|9MjwSCxiOHA+=&+S(e#N3~IESM!uC7jR_XD98Q+IEVeO2H5(jj|1*F$~C!lqIm zR@v;YpP!Fb?E*GPON~kh>CrkC3fHu1R9Vz;=g*|3qRQxoyfuFkB@y9Dop(X3nUUsD z7OGR*vCM042)s`>Iv-; z*)oD0_raxleutDFx?UNilhBk7pm5HdQ5{h=HT;J?3O~Q_zfa+?YT3^({O?ux->c9| z8UOng#)IYF2FFqCi~q29q|I#;(Z8a}7s}w6wj9I2z))xlVM>~55*YZBuI;resz^pF z6U?vYUE1|ZcC0Iw4gSDUSG)VJ-F^GcgEAhyeRA|I?2xoa??Nk59{meP|3a1Bw%wpm zQ&Rrl9)`D1jy{I%rv9Ukp|Ug`y$pxwWqAAK=w~=UKLb~^0{g;+3ak4WF3C7(tGc{P zBCZ;C|I7%2~+hp%nhhS zB94{&t2bDDhNf8s&zFELsbnnQSZp2Ux2=MRB%y&H4boRdNwEp3;?Xh+?fGL&UMSWr zk0SnTF^a;mEl8uNV*`+F!ps|Kv9)r`WKj>DTY&VKfj{-aP)nqDu1T=WfkSWM5Th%i z6K4E;FEfTNQ()^WYH;5~-&Q?^+=78}zO1c6^YJ(6dkQ1&s1`*PhNfpQG>uh6<@I0& zKFKC}s-&ZsUjf@`OmZB-K^msiNmL0|KmhBvh@_mTysN8)Y5hU$LHT zG^*m1+BGOC;$kilJzY;w^Ne(jr$Jk+iz-jm64@J2wgC`M%?jX;afX_5ic(EaQ!OF;j z$;3S`2KX1!*Qc^Gzu38YmF`I@R9+=Av^0Kfn^;TpF#3M@VWW3V1>t#~fErxYi=WHS zga$D>bS-szzEuGGWt6C@PYx^fIHpgaui>ou{L`9HFG3vDC)f?3j)Q%G`je*(p#J1( zpHROH|JIYb)DEUNs$X&w;B^VkfcHyrFq>9yUe8dEU`U@Jw`rT(BiLdWZC$xQFe+ct zj2u@g=m*6g(qu7z00d_^Z=bwFyF}GTgxw}MrhlGXH@FFc1>FSw1OFmkR4r@nqz1X8en!>IH@G@p2zu=XT=xf=A&{4_(WU(bBc>ewZFjn{k8cQ&r#Smr|Ij zj8G3SQ|BOT)KT@VenxFqRBB<5mS_MECwg7z*(gfJ?+3P}2C<4gp~=*nS9B5Pvyg*4 zkF=D@(0ZxzJt6_ExA*77jbI~4!I(v@4vA`xh;69@_ALj+w1ID;Ll)^8VT&21jL?%viVQtsGm zBlQXmLX(s{D_{WTVJhYhHo;P7AMTD2aK_gp1dbqMt_}Dwnb+J}JVVRiLhJWesuO>} zMI~hZUoIdY`TwdXXpLK)C%;JX;12(){6KdDP}6krGBPi4GS&Dux9S0vWe;%XBdg3? z!y~?}6dzI3*m6|8n{o{fwjHxf0;4l~2A7W3Gf&$QcV8YTey2>{({I2=fAX_A=clb> zs^N0m&h}17`LkM%@cjtWcSzBJ47skCDGAq=2~_4$*l(0LL=uNm3|E^{WEBj+2%nP6 zmS-|f7n3;0f@2sn^YN0wy!@|R@!&zZY=TP48=+2(sP1GmsGERG2-O7jL?9Sau3iT z)ks8cjRdP((HDnZysIkX_(t9RqEfP!b%tw2QOpxtQgz4o-fr~_!5ojoJ~3w)hICs+ zDxI-OA`ZazItnv05KWrTtpzqIrr+1JfOlmur0#{$6W5qk8LAhNYI&T^VBbVZX7YqM z-z-v^US$-FgHJnp)Q+)mc#uimcv54~V#0@W?9>_??riO^>+Dcue@hm;lQR|LSXv>B z={9!5L@nF3q`V5VEYdIFfve*FRG zf@*tE_XClELb3S%sFDue9oiIu)fd(j%C%dh5k(Mwve_vDh>`Imzvs)ZDC92akHp<7HsOxgS;1<% zjhhe1KN|tnor+$IVG>Ezi-);Pi7v&sE+P60@L78_cPbQZwsdfP_44!!krSecdvxd3 zmv+6U59)|^Tl_Lg?)HJB!b@e~Gx#6&9fujdxXhg0R^v1=@Df`@SvZflg%sL*i+Och z>IJ=h@}SvmKAnF-kpbF#@4U=isdSB~ox@{@zFu-Vt2#DS1Vv9z%Hk?^N&1f8qhR{x zB5b_lyan0&5Bk8IEs+#Gm!?Ttt1($8tUz+F*d-d*=@EeyvxgZBxyfEj120%=Ga^?72oC z(eL5xcQpfQHgXN{9M&K~*S=(m^2D{fK(6(dd6Q{F)m8N*f8LWDE#bB0sE}w2J)MT* zkiv%i`J}-!L289Hc=XzN7Ggb9NGF-r_K5c8AwW*`-?mJE80#dz+LLLdQ~wGex)!_Ug(vN za!H3*aqf^I{~vH`tQKe}mv)zNLhwX-G9w^d9XWp?v7tMNd_QRb1Hwo&MfjnU1o#Hr zJc}=}F8iTz)n7s=yMWD>MoajPr!|OKT>(Is+<#jFRt=WG$pjVohfwZYcQr;}&>_ZW zUs*Qz#VoDDxmag#<(GBzrAx(YUItQ@rw|sb*_~yBLap=Lh2V6;unNIjoFrB`i0ch2 zwumf0Vc-ug`s`y)88aP#UP0Cvbg`{c4qV5AR!>PqC<4V4=z@85C_u*`XKqbiPx-`w zXo5=TZdLq#(JAbV)mL()j04wP`D!-)>W|tnl08sR;oB*VkEIWJsKOLE9}=_>2aG@-LEf!MK09RkHEa+ zsi?h27hARjJ^#-|s=>=Xp@68WVE?EifJ{z8f|d;`67zmzJ2oO?c2wLM)hZ} zkk6D;_bi<)Zgosk+Wi=WQ&(DzpGib=_-3Ww|Jpw3E#gI%CG22xVoaU0D2B-lXsG*ZISr-@ zy7gp3qA8H}pw;A7AuNX;1&SyuAe|DVVFt%ZX4A!B^CItbh&*CbqatGA>hQ75gPbJ& z(_h5R4qU!xcpNNNCD9{MHxb?CTj7nKMtV&BcD`SjEV+F>uX8ti&qdg6Up47UGN!45 zgy(Wsah__aY*8ig9qMe{PL#>Yx<D&sDFr&Q6T%$Bm|31G9oM7G^e~1_T@-x8(@S z4-!Pb0!hxMu%PfI?-QjBpvT1=#ZMrWtoh342zeEoJDpN7Et4@+R=51JT$(GH=Bb$2 zXp5LY>VPZr>RsWyx|k5HQO~QmC0yZrJAW~E93oM5Y!<1uit*CrNvJty^rRuMQ&6K} zHcXPqLW4d?HG{{*35!l3I80;-4LHh3!cZI^ln6#Se=F#i#GT{v7$xp%jGz}5)MyE~ zY3~lN(&Z02qX*NYjZKp%F4;Cs!1Fa*rBJkNDr0Z-T$36mRPl3pNg*>3%bKJa25mnx zXatqx0|^l21WHz9)mwo}T9d-B#@T`dD3wM1Kx=sy@q`1>R&gz_qo3i}Sbq&AHG++n z;fx2!^NiHR85y}M(WuEuU7Ooj#K>p1UlhLb(-Lw~(@^8PLW2j zNJ{Q78py9YNkvF_H{d#M)haEm=wqG=R1EO4k?CDd+WZ*b+Tma&=>#r($|eZuQt(J1 z(2@jB6EH@82elGaxtqY`*K;~06@;eQ&Ru|Bt3_XktZ8%P@8=ogAL(PwrqYNFE z3~>RqJyK4N0(6K1v`0$KQGgCifcEQgv{`)q31|N_h?YBw%!7!`L7X^8k=YlKL4A17 zo?Az0=v5l_?BR5jhTf#XrpcG%CDGkcJ?Lvi800|UEO-h=NkAHolCa;BVCzJbMFIb+ zp(uR*=}{C8P84jWa#Fx$9^YquaR&UPg&a^A{ZS0|TMQ&%975)N zS%CPtMogEGh9lc|%JzFh>Rd-}_v1#+{+L7)38YKy*FhLl8D9K<8{sT5$}?K{>7c2)TJq+~sas#1oz+UP)<@D#0kwAr>VV;!o2Ss>Q zP?|azQ)HxVtI0SO;>2N)2|~^Zs8k7LEB-HQ;ZMI%X>jTuznOpZjnvV%+v)`2KaumK z5wtb9MPF3p7mpg@p-AkCbe1y!Y2Hb_uo{G>FNWvpwgstS(RQT1Xaa9VdLvC~8SEt+ zVa_ynNl6k62A1T^AWOCGfbg{u`B9mBae8P1Rj=)(Fy{>q7cHmhQe6R{FxY z`xeMs0=W^awZ-{Djo+(T3yGf71UnXLhPtX;Q*Zi{X_A}_=s&}eN>2tAW7WF{9t4@; zuOrJ$=KjQ)A#Nbi4ESz^`njHC8HaehY%bRmJI8KC+rnP8*99CjoN6s<$Sp@?bLK*5 z`nxGFC{v>gUU1IGOv=QJWnWpVqyAWvY0Hcmh%=j zzt|~mAoXI$*S`b5stWLo^6BTN5!hHF;NLWiCAT?@dp;(yFKjzTVCqtPF4PA6Qm21~ z;}&omnqbFJ+m=$z;nw*SyMCRqYp;x5`lFRwN_FTNQcsK)CG}ncwY39@~I!@l^UPS#bKMnrcdzy9HH&&oJy{ zmWrL!CTYJ@DTNuOix{(53s3$79YpABn*(^LG(gBCO0wVvn+XV#9E{*)6u zVw3qTXQ3z2uI*vMuq6=u?-t@l<994%v}R@D(g6dRv&}b*`JcK>&DA8x6B_dL1hYrw z51*WL!LHhi?0b6=GraX5#0++u_i#m5MN?DjN=og+Yea`+UOfzpn^wS=wDx2BF<+Bc?eX_`PwEkED$<@;6kZLBkib|u{Ds-bIe`Sq_2EG;@tEgT*tDL7iecq&7yK4U@3e+Y%>*Gc z6y?SLb&b~I&nYSlP{Te(0#Y*9t2J&B`RG>p6VhT}w@xF~NnP&-5|V>>xN1O-!Qp8E zIpl|^1mv(ErVfxpf0!yj4*j8N06E-;rU2w{@ALid-}HHE&UH+&H}h1(a}<7TWvN}P zPId#TKwG2jMJEVV6n;v3pdJ-m%+}a~u3=`oFk&U}S&XfFK>;3BojVo?(BmBoz&5yJ0p=awu?S~7g$rSRV5j3o z$ZL2VU%GY&v_CMSfgNqK7eZnPfg}8&zoxxq|Hhw_Ob{k-d-K8Yg8{eO;!Y)}e=bx+ zMF(Jxm5#dKfArC56hb!+Gfw8EUKi;iqWD5FB~nacJaNr}9)&|agx^wbkoT93u@}zB&Yo<-dmx* z_h7i$y#`K?>4|P}I%u9@*N1}uUgvPIrui)gg7maw#BgtOOP*rCGLuAL`tj}iDn>`Y zGWK%rNPd=5|~C??3ZNU7ma&=4kh(7c-aps$)-b2gdncS!d_BXh<0m6jd`px9^KpSsz4}zZ~1)PK{C#! zomBzyjr+mM*fA5T|=yvEb@r_0ypP7Sp?0Gs~{Gel(I!YP;N z8p`|Co0B_nzEeC*d8A0@l4`%Q)`0ex{M84BR`q9;E}i^r9j?B2!wd$1ro0$S$u?Jx z4*mky1i0}ifPj{)^d1hWL+lv7ioRFfB>dNB7;NsXJS%Q(rfJVF&aF_d-_`KW z2sNt@HvRh(241yrPjD8gILXzn9Th$n1bT(ziO!dFq204t1&jxBL*^O=zk;#J{*BuZ z`4@vy19_Mfsvntv9|&WN^y_C`G$XRRl6Q9_aVeH8G&sA2j8tiEXEStMB zoh}(3sYku$fyGp_=dK`Lq~@1UFA5P5!z6!<$Q?}vqq#u-y6&*!XDc5^QF#Je56_ay-8dZlGiJ-93N{2sV z5!d^rkq+6Xg$-zAhoF8SJ3CUd!755i00NeuEUkq26WbZtAMy6pv+rKKx_NzZb@uxF z*{in*R6m-NcdOKKg8O^4M|XHd3^wXgJ|e9={|TwizS(H#dx^`i^=G zqGQAQ316M2Nm{%;UgKSZpWf*(F$X0$Sj41k^Dq5xY%I@Ly*lqJYP4B_N4rOa8hlhl<6PgNXn;6Sa@5n_fxirE93gNR z7&=4hwIO_X3@YCc`-TApAP%=`T-EOP4)C~7?P3Q>`xyMroEIlHw?ot86{C$bFP)K97Ag~Y8{kl!rsFqP@T{9>AVQRD?;A7G^#Csg-hDeV^ z+nTU;j0@@>57Zj*gD?-RQ9r!;P^}fPpGpQCmSyCgiy74aP^)L)lbx-}c=C6>07v|s z-9~~~@hcfP${xkRDjDFw9(D08WT4LiTy7pWR^iGd-RCzK*Yd~?Uug@6<6z!SB;LQX zb3cCQFP;eqzME}f1n7g^#Z0hHb{02i{zh%zpy2qM?}w9gcWSSZ7qQOak}WquBU??P z0VDGIB{GsK>UBhV1=7vmqpL8n1aH(bi$yMzwF^ci#<(6hIRYv~7wQhgsFy31))vc2 z#4*)iY0XKXEgP;DOB)UzYE70lJUramEN!@WxHVc@a&heX@Zf5;w81}G?UtSU1w2Fc z&>+-+=2Sp-kMtoyJM|dxA61vo0`!q|*eu{4O`A;%_}Hp}Sm4J~5yV11rm7$X=!e*^QEl5s$HL*5%oKii496#=Vf3`$Agi~de9h6gvQet!^rN5 z*rqXthnmLl=i_TkD35iGF&sPyjR|F9lg2PF1859%F1FR5raix%5dcnT1#znxNR+uSaZT~Q3AxLxlF{Ia;m;s7qz!e zT*qzul2}u?2_9Tr1c>On{?c{?Z@Cu1d zNh1#HliI>Xc)TA*y=5w?m$SUjK$m1@w4Jzd+HET{wQiBtBG)DilXNoc-`#e9n2DPqgSEU`s! zMUoIHMf%02&K4{3h?ZZ+7SC4UjRD|78pjPRPKg_0kQgRBig^i?o065;E$+iwn?Md4 zjLuF*_Tr$G@%fSE4?pj4u&&E;w?lTY6jgW#PU{5ylW9rM+};8ctqWtLGSVY!d+3&8 zDd@)u^6V2uzG+OTo{cjQyhA@R)jP=7%9kC@2BS`uJh3ZHShaDJvT1u8wi9pH72O$8 z*6muMY}3QIN%$s_&48}a;kW9%X+z~qbgs(AcBhps8&;2Gkd+1Mhj$uROjo$vl`Pjz zWf|6Rh2h_9x9V&RX12a%NqdTw?Dbi?fGN4{Xub;Rok}7)1vQ=C0@>jVStD102JPzB zmMo)^QFzR_?I~9}mG=dWMo*B^IO z8%@-vb0jxi0lne$rNT&{rkEnYrplhb_P@V%@y9=!JP?l_e3Geqle+uoToODK=M)!E z{8Z$*yjxO9u{*Jlbm6J7PG2ObNZYHcZ%#k1X0pNSG{}cc=jH(}8O}rNf1B%aM425a z1AL+EMXmpYTi!+L)>T8Bmv%8nRW0AbR1~3s12Dwnk&q0`yI0w9| zG>-@AG~ijNHj-1aO(8NrtWgSOqQM*m@Uj;Z!FCA$y@R%t->43OvxS|Y?He_$KN}$L=gt0BReaeRmZf>Vzb_jW zH+2{1@ZgF60_PE0$SnTDD|oGvMBRfC_|(vJ|D94H@0rlD?3`nQT;CFY&2LZeo(kao z5o49IIvH1V+oPa!ky9=KH)=E=`fj)z zt;LNR)PH_Hr=58`H<7emTv+q@^v2Md8t2SVF02|4!70?2rt}=cjtbbQ?0MzB9nAYMYU|Nfpo6O=e-nJ9?w^a$fB1Q=aF7(P+t=zxTc5P zYiH}ae>$R@EPs!!YXGCig}#c#BIe4m%Vc#Er@GqpCi=F@`@PJ_`$c5{qStXs(Z&2{ zel60pmH(RZ$VCRva>+N1&)=A-T=G;_Q0&0O!+CFt6`OL=T#Aq<=vw@tGJMYpo%76W zWm4$m;U7l4`B|$~wrzqk38F4fYDA^BorjPN^(?}+fXRa1VG1uGUYRa5jA~8XxB_Bz z4F6mv@jT9xHCGOncR-#_UA<(d2dfvD-<=xPWQKQ|h2iXRIQ~s`xz5JW&bmHKG@e&R zGSYl*44sFP90gz>PLkU25a7icTAD7_y~)yYJ)R_8tV8FZBu6`O4<|+8_%|0GUymd~ zx6A%S=yo}x4Bak6C!r)nyO9qlMd2JYh|x|)_TnH|j=nDTZymA=?H;gOhGDSOSj@pC zJ2W{S%)Pcl`(-7ckG6)mZ&l_HpNs59=ID~hvEDTv(7C^d1lI(9-&NsG71z=BXwn#= zhk8wSSmle}lSom6682_LGqFTcktA@bE7)6qR(u_w_sN17>Ac(x2=R#|{);f+Zb--K4$_cBfJ#!Ag5Re@ZbQXPHbz2g47WX-R~p0x1n- z^gZ;UaW3W&%`JIos+}Lzl%*%8FrE%T5ke} zr=mOc*&Kc$3`E|nMRf*-SpZ+mexFm&+eId?<1X!Efslzknl6#lL7T{K!XMf|);jJ1 zwVYEMjXB3f8Sv~biSc(@7fmpfNRsj+9?`lA)qMUFRPw@c# zWGgBbihYBQ)mb=XN7)i~eJiph=FMyHs&}{$n-igF%9IAW7W3hUUXI!CBmBB@d{)T6 zM#XZsNrT4`gmPEWhx%*`f58(9y;&XV91L^Wb9o&;w3SjYu=i?WkPXQus&sat}^rNN*8r*6)$J_5)*Cw zj$Yr*R8rXmawIPIP|aNw5T392LYS|j*94v45o;ExIMuln{^h~8*B5UbTG>M;(NlCM zY-6o?A&@sHI3pi&sRM6NFWX7*2#v6t1oR=>iw&Dez#O`Xgs;|@M4xPZ^Z2zfCP)w? z5qoL$7CbbdJb|Or=%*Za-x!E|n}2fnUE{@VA6v%d?cn>xi`#%bNv%CtdD#Iq;ikyM zgvAdN(yTgGIXtpfQ|b$w{gW5TL~pV_$(1%)iq*9;ml;4ubu3>xMp zWgK(M8U%Wa9uB=(1-wvgKrBQqdQ!$aCO3js7M$#!fu6Lp;MJBO*Dv``EY+tT$PD& z@B3jivVo02&AcMz$TZb~Qkg9IS#rwvOy9zSnsarNLas)Hw*`~xY13%&Ld{pUeYG1D zhWIGboI)mMs-IpRSD~ZRTZgO?(L;B}s^WKKUgT&;$XaArBi>#044OVab=Py& z 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

    n{aZIJX6A0JZJ#pIW;+Iuve?Eo7#`rW?B6A3R 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

    vncc6C2Z z9zAT?xsi@1YnA=i%wIv4O1>@DuMe`J|1=zG5Z~q17Phh;IEx7zV|Zwai1x}<>`V3| z0~h74;u=d&Ts3??qVJ)`rkRV7-pL7Vh&Tb%SC_r|g(GL}j{@4+ep(n-gwp|e*{NES z=)>0tuD&vEL+QgXHGJ*K$G$W5;O|oPp{_dh$y$%j)(VN|Cbxk?zLcYW?c76IgH@U{ z9n!TC4A6v%B|#JT``=yr2)5=YMDn7vk$pqU^l;I(_p5npsxdqj1U>eY7gzwGL22z3@+W2W#RVh@Z|O zAL-Y{>?RcIaHQAL&EviOGgOAG!GMu`e!Y+P&D8~@$2D{x-KKu*zYgPuYJr;vP0xzc zb0&rzgz?8rQx9g+c^p?y3IC{qLUQM-_2yeSQ9l?D@^(7e!b1x^-{wI$Z=VAwS?-ws zbo#zqVZ5^-aB@o!6`-tLw{|<;yEU?#xpN@=Zb3KG&4RyjcF$p}uQusCA9JwnhQ08b zV3?IFKp#L{boMu}HJnuNB@UCUZ5oJ02AWM>~+T%ncRP7sAxZF2GB3ql_I2YrXWnh+L-EH|^V&q+(x+B4V zF>z!inA*!5v9IECEr80oPYP%%v%v>*s;}NO+_OPeKG+eg$@i-i-A@HE$c|p_N2MU- ze}Z|>m}ILw@kYn*f7ngp>1Uy5G02V^`DRyP#+lU|$XDg^7s$NyNJvOLOgv)kyR!o` zuW`5bynljpFxrzRLfDu=3xaqz=5Y$1Sh-+{@e zUyQ~5g6NY;Iq7yp^mP^Vyp9GQ{zorkC-cSRYrl*Z8L@?8hg)L=uI(A8tWUwdp4)=BEm? zMK|ZooTjmmGj`@`a6jk}Vm4iKp1JW8uxzIm2K>*?_c@SI3TP{?wpn(*Lt$2&S}(vEpz{Zo`*@1R;r`K zL8ET%m)N6|sFtU`($Y1L9{Iaf_H}&;) z{1x0TN4~tbt<=r(d&n;RE}sdDQO&Z_{1(cId`w2i%(6wW5z}SD$t9f9vqmwq^IOWL z@lf4A%1Y*rBU=4kOkMl8X1v3Lpq@SK7~fU;h6?xKn;Dsc6H&AE0)*-^12^8tN|PA+ z9!|enDCJ$lvZ^Q$J7n%&Yh|sF4MJ0#V3Zjbi#|i4PIWn|H(WMKDgRjDgs)xcxbh4) zyY=re^33u(b7YTl{nf28mMEQh5*qS>@4*%fBI*8Zp(q5kBHzhwP-Tra^kb$cAd$)U zKyRR6o4VO(&NCLlr-g0FwCUY{QDJ(-Sn0g4=hAD8rbD_jg7G?$TyhX}H?|iFhWtL) z+Wq^i*3-tHTu8^kMLtm3Z!9V$8JByQ-|Qf=rkkAfy24Ugg`)b{a}F0a{i!aECQ9G; zl(i(RxbMw$-p_X@AEfl2gQpp-Vo&9T=0`gfus~`%6%bekMBkLBJ`~(Cgm_nbOBnxY zTfCPYz< z7vza}lrO0*-rI=gfoE1@6VqMl{z|99&)5x!d0b^M-jX$ZfSgKYOM#5jWPJX$V=-PI zqfJd&D78Uq){ThAKpY}edRRxFY@dBqd8U*BsWxT_1qxU0 zn<*nPnF)7|Y)K26b#IghHkfIC4ljds_0>{188h5er)ujfddQ92xTNQ6(*kSwI*UmT zwOwQDuRK+cL{ACt#{IE9bJ>>!)=$5mk`{8i$MI0rF7Ptm=|Dd91`uyl5&H-`={VsY zZc4L`r(d7k#{>(YI*8OMSaom79t!oGh9{5tyUZW`l>N;CeBsgTn zGPVl~Q!+A2=4>c-qE(V;svb-h*kz4o(6E-_mC*1D zYsLHPcmw&kn~jl~#?No9zH-|3<*9mELLe{+V6|rqGEhJpn*5kneD@`eA4O{gucSBY zu|2*jBCcw+h)Q#bywiPQ629e4!;>C|nk$$#He1{f zGTN$$M=H!W^bjU6?Dnyb=9DwUmYq;(?+t7?(B#+4HL6?_!H^+9h#LLSLV&xoa**Zy zJWQefHC(gY@*K;wAY5pd<@{}$EiL@O{Hz_CnXUIsOAb5#okT$>ews z>q6*b;}fAR9%t>%Q4BJK5eIY{wi#*O+br-`a^hDW%ZMxS(7e@aax#$bmdPQqFpF`n zRhH^(#?UI$;8&fT>5*uxn4F30{*a|NPf5#51!K^BQLIFngIzKg+YX-fDDr`kL0Aha zdJykQTx-J?ZOOGu*MJQ?%?P85t4Z9MuiO?{tE#y zS)P>LebJ+yBGe9SCQD{I$fVP4dPZ^FSuVU2`j?vuGU!U( z$YIBI3)q)<%@55q&@`2eA@Zu}t4l)S_Ppqj=hC16JMgr>BuIMkxTbJ09IdEwdAU%0 zHZK=@wDw`b#2@ySE2oa$UMz?D+|H(@vX%Y2Fnpy2KEJ-mF8ld-tNLs6m;T|462oEGH^S0tLW+x=`xs4m zU>v+l^+Kg?hA5kTuB?jb%*T0{ZjDl*EX_n~QNj5$hFz6=Lg?NV)g*x>+*-aUMf!oo zL!xS$!v66qz~cbr{UZK%2{M8ix2t`(w?6S=dUI+s^LZ++Q&r99;8s)cu&U;6=H}$p z1$%Z$la1_nC3NV3d$RpJRLleRn#}7T#X9S{O>=Gs4(4PBnK|p_eK9dOu+7 z*2)sXh#8&-n4i%u2Xr4SJQqw$2bOjSKH=lqOCTwpO&5d(ai>0E)kzJL>iHST zwt2tk?O$QmUwIJ6!8|jUTw76_yerUyK>?8p7;qn~gGTP5&jeZOt(v8AL1g;TeB{N)c3tuH%ewQivM(b&EgF{n@pjTy@)fah}p>`=ze)IXo`C27; zYrMq3pEa5$N8gxl`dN-^uItu0lc#4yD+#-m^%^a&cHE+pw4QNjwc&=XV5;Vv(tYkz4X5OBRkunWL8V)53>*CDrVS zq=li*UCJN_2)2+gs&5W=#2ZbshBZC-LcU&Sh%j~9$i7xQ1-W_B&J$oA6g;PA7gcO3Vigp*&lP`f0 zJtstt`A3~S4=KI=Hq>hEz>Qqrg6wQ2P>&y;0O#NW^k?KTz% zp@wEWhxu7$JLwf5rlZs7SFDr0f%GN$6UD9aO8D9`mLnm19uNpuDl&eYYcu`iJXROn zG04%J+9>B}CY{kPpI)28QSMU-`BxCa8JBa_ri^4CH$UiB=TQ2}=spdZKFH-!S!$Z) zowgsTL}8vzT!mG=S3-BpiV7`cX6j~7WURcCgQvmOeS!h;d;3In4k=Wb>jMsdJLH6* zW$O0{r|eYx^2e|OOUG0bcn2ho$O|_5bhuZ@0tMD-6%XP*Ns1Gwk=Vin`vG(D%z_ao zLMK#pA*HzKilQ9>9Gg!boYz_-|Az@gF#a#S;=7`?Mqy zjBf7Knd^VLWK^asU7^rW;Kx?w{xjr_NLE*x+I`^75jyg6#wUiUGzU&?S%gxnfiau0slD%QvWycj{`Un6w^Zm8rc7J9QQw{IM6pnd`u{f zD!JAi$p6gT*#BD~5yk(SrTs5_h9ly?w{Xnz-{^)?JlMgvrQ`Nw3@94#V2nu3JtjG{ z0w^%KZ(31)G@`*6U^G8_TpAphqB=vB`u}^24(5t>KEp0V{?`Yx z|7AKrQz|t|H=_TaKp+e#D+_EVi%mh??0AewGjtTX5}->FfIp8+@eL=u&q+m+$3o;7 zZvpE&JJae^HPLkgrASx4N{IiFQi`RT(kv^$;R#FoaKAB}=U?>@yQ6enxda*sJ^MZh z57m~6m0YZtP z?G&>23GvklyUG)c;_=~8trIsde}Y*i+AN}USj*Z}@cP{S4RxV*&l5DEVqn1`N6IF+ zTNu#9qQ9{-)60X0qZGS7P}KzwIFAVg2;}@yOiY-b@^RFqu{bvT8Ih{?FA_wNCm~;< zrueU%i9k{;P)sHhtVKs*2Dz$Hr(hjxlcm$tpW_!){@@(7J>IWg!sdE&LKt@=SW$bT@EWml$98q=-}LlR zkO`o*!h}re5b`WWimFXJAxb>Hg_(r1w7Kgcfg^Z@sH3QpVr{}wN?Me{JOiM=+9FOw zE`BX4XDF4hxk=4km(}|m3FI$t7#CK79ie{vHsJeIWwY#rdxl~?-d8TkrN>ve}lvYa9Z48|ST$aPoX{aQ` z)^FoXWFm5-1#&rnJcp7KQZRDst0I@295;+JL?|*j2r3rZ_DHIrBWWsgUNXxU|(6o?a&abE< z)JiW=cV^U_bTCf|7ji~PJr?(MMoAk%%+AjEjo{paCbW?^dl1(+4k03Ly#c@ZUBg6v{Vr#b{;f><6k9;&fK0H1*Gijn1nLP67oS(xe`s7mRXGt^_Gz< za=wmCNi(teb(T5#onBD3uCIh#TPDD~h@4*RHi^7UPuYKU)Bwik0I-%&<9TZ6K@Nq? zDrWq2&yVeOV@DhiB0$VTg-uh9;4#L2HOXJ-)B|_oje%$FLck&i61DH0Ce?9}wnTm? zP@C-Urh=S(sA6OW?)_+wgWx8lYod%5&Z=?9rl>IgSkdRx#ln!}0Lic*%6Dg)u{3gl zVHRn%idbeUXa!o2@C5WQ`a#;8=4rCH^Cgi16VqFSW>Pr^UZ3yHLPQ=don6ub2xxj_ zu!#KAdfZ-gD7a6l9SG*Q5Q0+Pf8!Yd-w+U8hOiKW9~^y8s(%v{5&%m^XEiX4ro%&vu< zjpe|-H5qb)O34|<R*2aIR}q*nBb%EbP`$_`zLa zM6ZRS!DvW?SR_|EUtAhQEFyH}Ny{)wQBr2t zCYfvo>ITk~Gp4aZKrraeIM?>r;zTG2qKbEgUxYBN5&YuR=_9T-yMc-E--2iwu+9~p z890`xAy^3EKuR?lp@=l##Hxt0>)m2n)S)meGGgM49Ht-f8v;veq|FPm=MwERpLX%kJP@v?#|V;fE%S!jv0* zZmbH-0l`#Two@T$bS3b!y2qwAlT3z;0L@4z(y^9;w5nd>0><*f=>{ZrSU?7`lFMUt z^S(ODQp|M&>yS-Z*dfw0R7)ujttk|N7^Q_~6FaoAnCNoG#!PO~OpVSVbpf~Db%aur zM@2FZL#Qe<3sYcA5z%%MCaZ8`>`3H@A>^XP3c2+OjG=!pbejz;tf9d_sl8R?5*Za9 z+K3QII9L)lp*d1ibX+^M!At$Ym8v~N?<6u%G!rRBiQsb%4~FycV)>zp$gH5!m?1;% zF&XZBAQ6tg((IN{Kc8H?@S<$2&q6 zZS+bd&ytjYD-GvGhiY z_t9jOYD5cawxR{VpkHd;1z`I@xogyK?PTBAW>Qe)0K%ek!=k533d-vsMd>dkBkdIO zN)qXGe5?n;4^BI-a(#9f!ej7AiHX$`TxY5TXP|EWxLRYU1Mp;+0PsjqSZByn5!ltU zrwMRMX#uJeiG$>MxUiz~p9aF5X*4zw)6!Pox}4`j26~B8x71|_U}^l203|C)BtjW}*1WpV zIg}U4@e3RU(n@b;`1GmPo`^~O6C_@h6D};X9N1CLuo;e5=55j}>~S4D&tYc$+gj1x z;>;3X!##X@((%20pGGtMr!6Y#x z;mj%8F)~23U6eB5N?X(yFrws8{0OlW$D57YDK`Z*;KN?nR1+2Hi-xkU%{K*^$PCK* zp%&hnNei5za|x7ktK?LIs31i^1)9Pv0u5Y>iYq0!rmh&?6Kw*J+7ylgBF1!^C?qW4 zTi2g=C86~ao;n_QgsO2m*v{5IR{8xh*L-)}3=?1lmiuYjLY%sN2Lyq4&;Wv40DV;i z4W!bTe<&Chj)lKKiXv*u&Ygl&8G@wYS!x!t zT~4ac_KW)}*{*V>0Y+aratBMtL{c!IZ%`FYTo^@l`&188tII)BNuA;=L}0w%_J$60 zB><(Op&_$;MF0!3E=87SQY3F%A^{~?aKgYb75U`py^!Lw2=y2=L^OV(!6`GwC(b8F z#_P>D8V2QtLgY9iZVEm+W77H_MA1ocxTK&6u0ULvA`E}9Q~{+u)?LPdA;loDR#89$ zIqbGwjco?|g!us}Watf<=Z+&h6{n_HQ@(6~wS(hJ$9V`oXMl4#Gf&p}V@N~DDX{0# zU#L0qqn7GH;fA_(cjE>d3%2_eOF;!*oKi?Bv!qJ~ zS%w0Qcs(kaF@m^q8CL*x`otLl2E-Je_Djv%v$*yP4H8J{#gvLMMH#^E8AL=G3!Af) zd7ph7E%ORHSfG=n@)wajVQOZ?@eOfgqiHfTABF5#HhB5Q`QUi*Z|L%zT`gfw$LU+c zrU6$J5@s)GIfj6-tQasz1a@>U6j6jvdvUFesNC+O`6%Z3d1b0Auuma51ph)fp z>-+&-;6t{M@;?G-v@X5jid& zK%n*)a0+qVcO+UWO7%VEBljZGuM@07%sEqj2|y&C(wTd=u&tOih=LOK4A;C0&La64 zFsGAMFu0}+DUj|22pvL}f9#QH#EvZx>^n~@hLcmHmrWV%wai6xlRP(?SCUG> zZNxtm)WcXBOh_~!hXiRcMtiC>;_gich(@$g1u>M7aB#yEwUEMr5G*1^|NexBj*a?- zrBPRv1M!x?L0cd7*yEt6&tgP1F$8+GlAPu$YsOr`oXG>|u$(4UDS+L=Kurp)kpQLH z$>fk&F%oM5GK%?_IiN!v9zOjl5u zg|!ze>nbnjtWmLOk2`?6I1afur9gbL!@Jax&dgpY47onPy%X-Y+b2W z_f$_k@rMMjL4eazMC%dlx})2KeqH*XtcOpw-&bf#Q1V7Y-kz~9K!iq1p<{&ylk}x5 z7Pp|VlFZ5k3qhA-eZj`Ta7D<23f@=~$mX8Q#xWstBN&q;ag71NhE~gPuwRiWisBnq2J5PW#i?WG3H=>^ zLFcqjp}SJiO)%E(jSS$i#8IxD=*yScA z%3hG-7*Q;OwNJN7We(~7(0FxVy{Zw$8`$CE7@*k)nb%+fPG9s|8?|ZI#@+0<+e{Ie zhb)p*2(cd#DF>R}8F6U&)V~h67m^uNA9AKg0GsEfN8CXC72rgC)ehT#<0H2F?g_Y9 zZ>CA);zbQgf%`2r5Iu6}_H-One+6nE72(V?!VQh0&eX$vrl()KBio;)@^b>0cnY+X zc-J}(HyjlPD6i-EvYP}N+4Ay_4pbS$Lnskt4e^#28ITk)NFv{k# zO}a#dhu^^yxT^|+YLnyW(5PdIc!*F3VK|&ZawVmPA?)RtKoZW|TlO2%pF8UZ*iPw2 zSFf81@x}lsMe)M^Grs=}uhoB^**~Le4CIk&mYU&yGO8Nyb7;Bmm*#rkL&s3dfzD~} z($BQd2q+G7tTn_GBmf-zW~a3su%#Xz>1Pp}w)gM&4CCb`xbOc|S@}B`-|M{wWB0is z?9Jcib6?5g{`bq{+I#-}c80Uu{p$!H<~t<3G1JChoP7IYWoWqeZeb@KFSquuO0`&odAZehIP)f+OOz*Ie28;j#z}Ij+ znV?b-YLNInN<^g2T*G4epR3r3q$8NjMzXwiOA>mIvd>1^dGpriWOI^&EdqR~3F)Rl zF3`%BMFUoBS+Ow<3s#)y81&-Qea5Rc{`JV;*hYc!LCjD=EkDloK3%3gr%&D6a3E#w zru6-?w0iS8DuhQv!_Y<5cFbFyi)`>9DaS@=3pxJ4^!(9zE zC)Gbc3`yW1b{J-p=H>HKdZct082qo?-yUiL2|nO-d=h=kBpk9pQ;~U8gEWzI=m&kE z<`NF5kXNJ}(m-92d1Ql}pz6+ zx__^qhJSjCi+Mpnh((E{x3&BOZrp4sPOO)LKZYg>xe=!0&8?Qw&mh2j?u`9u`Kp$t z+h0`QV9MclC+sg~%(KG=coPm8rn=GM0HS59v?98k_$Jc5LXK4gJeTtB7LT)Mymx zTnf?{TT2rnqaB?!jRxaY7VKh?2AVnRYOw#rg+bJv#WU+q{N^9aaaqWNs{>sf&fn-; ziV%3qzq>gy(3A3fXsF6b1(ZNr;dhm|2&rmat7Kddm5_LoU%^O3OS&LSgNk6?>t9~W zm=mHaWH1(Ec&hW-uSkgt9)UlC*d!X;+axq)SVBw9yhha{Uw=ngl#_Hz{u6m{MlqpK zh`x_Ux6IB3)n)@GH0?s1h9T1x`HWgfV8Emy4kd1x#)v^rrX>t_QIHJ4T{0vCc9MWd0hPd>%tg*wxz;g7 zsUlEN{5vZJAdS3r60uj|B0BGp%czF5xI&=@lPI+ShJPY0pnIbfX5lERIQN9FL>3@+ ztTztg>k`P4AZt1HfH`nW1tUcsR~1_PL=~O9Adx^i#FfAFvE!{$Muw%31VZAa4Lm6d zx1Msz7r$OB{zW#ZK;}uyS4SEj`Ibl;aN=0Lq*x*+I6zJZx!#ow|AcRf>@?Sndxm5R zNCK`%GhUJ9xE88`kkx@o!^M#;oQNn2*HX%YKpNOJ`@9}ZwR3|3sLhS|fL0ZsJcB<% zOP+a25EnbQl2#-eKmjcII4}hNNSdPzb?c>iG_yx3lwU+pRkiUcpohF6|2hn%ZhQiA z(3p1Wn4k+suJ%cC=;w*9hAnHP`zME~FsA;p0d39%uspdg%!(T>?V=JjYd*LtgT1WI z#2z<_aUK6HYP3Wzrda;^+n2d=hY-OzS0Ep;Rb9g2bmw5-OWbbFMd$r)mDr%gfnbc> zlLi7wf0`&vQ%7Os*Sa`8u@O3x$jHzLB2qM>un4UbEK(!pzrfKiba&|s%5?}bZhK4* zC7ASN?sKneMZsm?=9TSM$Pzh+X!r#^;h+G}G*Bj}B;=Wd0x>R_J5#8%B!j+xlevU! zLSlh<5E)8MqCqMM9%@Z;fohN(>X&qbYETa7HrYk8fkcol@^zwtP!J7ihg6U?S%+TG zH}VeUATSiXl!HXjHd%*qP&a9Z_&+i?Zt4Lal$_K(3lx49o==PNoaeH0&#p3pObIQB zD9`9^5rxcR5$c|b3P&(9sJv34hhq%k0&<}(vPCFpuEj>(wl1Z5gxX7Xhe0e%(VAv` z$I6`tT|)6KQmBtHlIlb*^A6K89-%91&U+?kf6@Uk6n>Jx*0d>jKQ%K+0Nis-gd%x+ z+RLe701`;=fZifFSPqT-_tnd001-ya^Y;leu!NWp=V%h*^uCj@+p2vV(zA(&a{<_& zO3h?!zLEq}V`#`8G=TQMQ!l}W8ihwA;&N*SG)9iVLJ)04M^@mJdk7bAq7Sb)MvHgR z$N#QL4-8GT!&Bb&l7z~q&?mMaV;3ABP*B0RCJcF~Gsg8}{uCjOV20=nd;Bnh0t-Vx z-UAVu>lMXFBPJ743u*v5mM@@$90%m7>;o4t{USo$0*IOZQMR=SKnQ{=K#{b5>5H7& z)g(+E*b4wrPz&+c3lO7vWsVdqe<>T;ii;#|u7l7dIxUrfFmSvN1tfVqq3aM;R0n~! zSpUO}Dpqg_3dobo^6x<&M^_F|bDJI5IObKNp2KZz5<307IG`u9pr}ufOA1#&KlUk6 zTb}I~Rf@f<=d@VhozjaT(AD*JP+b4RV=rcBps1Tlo=?~1zLrAcwP{t4l%rF-r(#yh( z$QT2d);(mGV0on4o?xkP(mk6~@~umSqY64wMv|7-KS1Nl57J_#D^=rER}ReDZcrg= zdC(By^()ZwT7(A$Op4{V=VWb06!ucLQHY=-u^luE-ee7!I ziWp-=5)1Yw9M!F0*9Ozaw0j%FMo7ix*s8$Q@uC%QM!=*juH&%~-GALN!Z+CNK)oE1 zN3GeCiU_8G*#ZNEM*t4iDFW_xLq;a$D56gH(vYN@Ay_Hnqqwr|2=Sp$4#I5PcNnr> zWYG56hrx1utdeY|1U6!jIEduelylnySOJKLkduf< zog|4-jd*Ffp)=gT0L-3L@?7C3f8Cj|>rE0915EHSEQm&C+qV$nHh&>#IEj_TSoPE+ zv4u&942KM~gN%V0IEl{K4Td(#I&eh!i%)qW(5N)oQp^|CPT9murBpF6h0qYyOz0zU zG#r54iPt?y1}|xqPLNX_vx;LXurE@itt<4EJNJP%gy0`G-y2GV>`}+1`|b_H!iJdN zphcuFP-%#gM(B#TuH?HZ0>k(%I|DX{MTQND@h=hJvEVywr)S-YYgUC?74n};LCG~h= zjGF^k{PFnZoSY3N=;($I-eLdJL1DG95mSK_&XhzfD4G0{M;t|_u$@}0&RLw=who&R zCbHTBM;0wL?z&>`m^*SuT)Dgr;(W9cMNE`#_o(TTyNJkOW34c=01_pZfCBs?PN(w~ zONIQ;$psZ9Ziozk1I6PuGXLb_L8BA}>c5Zz+_Q^t7)?^Z6Q|AV>9Bb`s|%Nk6y--C zBu>j|{>h+KI(P(NLqK&x69J%l7-l%eGSsymqS|9;T6B#7LXIzq;p55&rXpe|b-sVhAKgTnEk4 zcUO)0| z7{CC26;WEu5uvmNX@I?7Pc#)r;Dz2$T8T4pM{Ogur6U_!$!7y*o?^6XJVho@3bo5? zd=*rbsE`Gb3t5ab?2^9eJr=+ax(|TKdzGIFiJg)lNeEi3?22GfBPma<^6pKXSUlY$ z35nHD#HfcevlKk6POH%JL?ogXR$Yab0+J~8z>c!5RZHCiC1}<^`G1AsIQHO{a4WLvJdIf$rPOy93mxQPJ(%=zYIR$>!EMUguU6_YYO2A)mfga7NZ)Rus4Ne(%B5>H{#WGHP+>e54BQl_Nt z6RmO!zAPyLbgWrn(x8G)G$<1*(V#OmQl?so(bg++<1D3Gfof$M(3BXYPArhjEG7%P zu@P3|QMPI&8D%f#K5-WGg!p-6agmTy3-L$#LTluNO7g(7ED;%5C7oExQP$G&5|TPe z8^4I1m_V6XOjdSdqpZfGELEy9DqgJpYAhH^ED|RcaAr2+g`Jp4%dseHwbG2TXA_^5 z*$iEv#B8R7O03{BGZ`5cHJxVafAuJikL|{;MgITw%CTT3(#8gH6E%Rdticj0)dJ46 z1Z8R!be?i!ETv|(#jPU^07C8yMg*XvsXUj=oPI$^%<}(QYK72+to36lczk_=Fd)OI zf5_*$XV`4nnh7mQNS(~VWE5?u9(7F^Oc87p`Jr1ZYN|U8oP@M}{*qP**t1@qR3HTs zb;f?Yb~13nX-5dQTPm6=}i3JzEe3g}Z-$Oi(EO}U0>)3AY9fqI8!?iXN= z4fxB8^)tgU_LDL1oLQ$K`D`o-)D|7Vz!)y0Z4Qi3%&3`ORF#}Vp~Ls4hgm8hSOSU+ zGDD9PL>`R*!UZ{TJP8^yWeMN`vHWxN8~DSjQH8XMJOXj5+VjU9#^e1D#C{<_9+O3} zFByvwmu{Q{w4PHj@FuNA-x?u=x=}So7!p}529EwrN9#0^8QC4D+ld5p1 zV?ma8WsN;^)NfMoFqj@bs&8LnFo2&UDowVSXD0lIu`h{zW@l(1UQq~Co*^OdXLyfR zcm#d?>=$E{vpVR~4hs%B$CATQNRC>yON7V8fPz8;`c$Lpiu(C`<)xB;p3l*=5@x5@ z-c}N|JEI#l2VFG7GombpqUX1|eq=K&P87EQ?79YTx^@p{pJbht^W&i0YUXmiLeZtM z$pB$OW-OCvybXn}VWrTf3Hjm>D>(&(KmbpD`NUv_FR4}YDPekFxhFM2aKI_yy#@J2 z=Snbl3z-WuJ`5#TH&y5f>Chwew4}&}G~&M1h;&2%;tO&S;Yd#iCZr<+QQiuR=*Jub z0@`VYf+8cb2}oO}VM^g_LB7b{YC|BNImIUJQwRbR-{r^#1%r41On$RS!33v1+!%3h zaPXt)AC#qfT1j9u&;&%2GKh5}ktRy9>BpQ0$?Z&^=g{AH1^;FQU>)}4DbtZZ%w;XR z=Pf9GIlAH6%X0_g`1lCFpQk40D?`9_FXhgsVOyr}l6gEgkG%PM5(6dKq`w)6 z111?F=Q+yP1r@~mBF%;Usy0`F1SwtIzjtGkYdJmAMwhL4iOp`X6lj~B1QM0Dx;JuQ ztu(*L)Y?m)h{5lp|I!jE{-qrWheUsLbn97@0?==}fEw=4o2_18kplMKD!~A1p#Fyc z?dgF2_5%^_q<6NT===&UznTN9VOX3z0UBkK!;Ij^cT%ph* z9sI4iplKlUV90eFv;?~{Rpp0DSGfv2TtaK{b;Ds3G|P~LLJo}zuj$G_2iX>q9a3T3 zx&YZJ)P&Cimy`Ei={=ihdsQk36{SH=E>OPo93ff}ofd;&?tv(-i@fw4S3xNB9-%OL zmqDL8$2!S}amrPvO>f-?f*3s4K@b`l?#w)uT~bT39x6LBjolIp+lN4_y=9ibT~KnA zsw_d~(S^B}yi>H)d_^Hj#t4b-_1Tw#Xf%&;)P>KJb`*CVk5M6?D<(WGO`s*3;VGfw zDro^yE;ncikKtH*b%45W05wt=jiLZq7dlLZ$hrz}Dx`BNC1LZEhVKv^O8g*&Zq@ja zGW`prcmk^Qv3iJg>8ZmTv z-8d8OlvXLaG$ee-AGZ#n0_M^5MQ>}y>*K%rgvK$%(1#v+>%BlOyVU`8-e}7R{lpBz z$foGwJi0lH3CAriEQctJQom%}QVuveQeIL~z@Rgz zyS%%TVym&TyR);JVmD>>M0ZI)GOPPRJ29)P8{nm-mDTl_S$38;W-~k_TKl0>N4A@5 zZ!>l7g^m8p1jmbc_e1A*k&V2xa$7a``qt7yhF;1X>+=b^8{1ivtZwF7TA7TqygNch z=31DGouRS(@ldF2bQjB}jIw)QWjW1$1Lb-zWxC}QySw{o7jtJ?Uf7t7aUBl&iB>my zTbbcxkqrHI(zF@IDLPwQiMJL88*8a|7PeLs-0be9sP1N782HB4)@nmTXJac{wx#CA z#>Vnia%gQdc9(W`HijF+%$ar}%IQwH(`}~C-1H;J?)GQ%Fazd?za@WO>8=fS^Y8T* zS38HjWEZ{Uoya%RMFwP+IfA*@a|SG2zrm=z#KOMoTQ-5%%rYcff=k@no4a|pms613 zVeZGUM9|f`4wX*<_g=#h8Il&h{q*^`fNbX23lu;Z{{_=q+a2-Jq4F{E<1)_c3l;==7${$DWdE7Rn{^^iN;0aKl_V{F3nVFy}MJ zX*GHiXd{^X^T&9_bHCxjhTsCL=8nFg)g@RVN%DKb zWE!1KuGL1C0^b&Eiy8&t^XDUAhiGmXzTve?R+f+SZoCn@OtG)w`zd^=3iEY)PO&Ft8!oAH`-1}VAPH^s5ESBEbmTT^fHL(0?jlK8U*z1ceP1$jcwe}VieA}y7k@00y8@zhF zv@=@=tNd1k<-hf69Xuhl!RH2==`W|P8xwJH8{KdAx=R~MWk_26Zog1E zbLI9LYkTcIGa9e6FgokCI(@n_$|@>6RIuI}+g@F<8=5V(dhPAaHnUD`G2Dywnoy>O zikq*e?KF402J0ruUCW6U_mcesFQy&7244Q1=pUMu9HvmOGE1IEC696G3V|c(&p+S{ znz8W+&+sp&vYt(^Lik$jnPXm9o?_R7^59)M^!dqrnFM2x6!!6nAi)>&++kth;f3`Z zobFr8ZLq@K5bg$$Bkz0L;feFCurU7bWQ6(Z4OH+7wv-L21D$1yN4X3cm;5|nJiDw} z1lm^YbTS30VGrfu7`(=VZ%h7sK1aI6w)H>9Jum$>-hZC#t+QU9lF1|xu*)pMtLEOzU6{jl?@xAZYS z#pyq@>pA_-ebY;}%l=LY)$jP@y;}Ryn_cAY|KR*KUSod4`@9OH=iydxm^@75<-h)v z6rbk*?mCZ#GuK!8|t1?(bPOJtqHgnYq8+{B|B47rKq+0&f#9H&2U!Nr(4f$%oOP!TJ-%1;8rs+!|dY zTNb^RV9FH>M~%)_XT!#VZ~n!S&m--+F@3k`l;Y0w<`w47e@_*mR9Bk@2dF&8(jRcp z$*!6#6n{ z-+&>q;rb`rUxtseYxaVaE1!lpb|EuS0E{}p|aY55))8vWo|C9d*^T(eWi>CFF&AC|ZG(G%lG{EK&t@Z%}73T213 zg5LGMWBo8dDcCaq9xemy@5l_^&U&6O(`^bJkQt zV{nSzA@JQXg+-XA;0NzY(Jkun&(gUH`0Op@V?Z1xo4h`Rh)eCs{Af0 zxeECF%vjzE1FOX_I615ih2&ZmE5Y4Ud{3ISFpC7xj?T|DB^l4MDAF%;J&rX89 z%$y$r5BgyX)*<{}4C>w0b(0n0GGIfRpQWuaGeX(!r;&(eiCTH4$uO^YINc<6N=}Co ze*0fm1?3=0+ae&+rV|@<@?cYLB}`?7r3UiY=ya@CK>S*swZ*a4Y`XPZ7d+RRlSFuR%)OWosXQ{eOh{GZ>7S&3w}u*4&lJp zm!y{ylat#5eC9!vkEOw1wu^*!T9`^c{JX4?|Nhs0MWP+0Z1nnE-yY}N41e!KTYQhh zU-5jGukG@-n!a~1dvEz+wtf2@?&+_o%<23Ne;y_pUVNSme1z-mySGW{f1+U@-p86e^an^fpaEp~`LlE{Q-PlF%OR4_Ggc_&Y9fgKwT~Y}Wsy3o`ZF{E^)YD9Yq9()z2qG5~u0NSh%w1S5GSrsTZ#YCVlaxt2Dv zPv@M?N3yd5+Su9XZS*$2a$W5!VVakjZE#TH#(2DeaMH`?o0_dMbI_e7X$WVJm2kb= z;0K73htZ*#F4oS_H2Y;~usu<+aFwUhI7`QU6rR#RrB?*w-sT13KF55^9BvkaP2Se~ z-M@t~2&{WATD0plUJaI0`FY*1;e_4&pX;XQWcpvm)b08EJ_hs6&cbi|4Q|xk>HH1W z*3W&P5cE0QZ0G*8M&jgs-=nSj9$k?b|Cra{XXSqmRQH+dW_7k0KX0ZoX#9-*_H%w) zmj64;z~BGKsd{()9+1g(+&)>~_qfKd+3z(P$sT?;)BijEQ*0Zf?|R34md|w+#l3ZP z|9-9Ovznjtd}6o1qs-Sr^Vs_5`7(dy>sSBxReS9%X1zwM-=}+$`;5oyXn9rjqkI4J zT5I}hZP&w4WT^h9@b}BzFEc;SMg23-`tOrGZ$BrkV+8)UNr=4{H~*shxVQGb*Sy-) zeg2nLgui`i*%G!++&teqCnzcRX&?`ddi;+*9cH{27e*eUT4dH(|-P z?=P!$vwu?dwra=4{WzkT=OOXGc&iyRj=lQdG?fW&U`uyuu`}dyP5AUYzC;rZ{_s~&q>z!@ym$^7U>b}FBFpYl) z$#+$LY5gYWaqfKY!I6;Li)X6(-PhbWyRRRI=h~7!UU&E3ncQufG&NhVV_)+;TfY0p zRSaM2_4Kj4j~FtVb{{vJ-3il43jT+p+WHAszoQA1^Bk+p-tzJ@m~O4DrS)3h5^vja z@qN7ZU$nc;mpiEh@5i?M-Azo_+)M2oZib-`rdjcz{|?I{ zVM}d-8iu^u4R5($AKQ5a_&sEeO|(`vL!o5un9`(!zu|>92h*XK*xFhV3ET z&CaXm*t_fQ(fS&5z(H_}hfQ@EeO@X`xqA$yUd=^&m54k5lz&>>CHi$SEAR8_NHAbn z%OTLp_MJMXG9@Em48#f7Vx`f0mwBf#+X_q)BLA3NXON%NOhJ<_Sydi)0S z_nY2+%ki{XygAqDsru_WK4(67OYj?fJF^%3sw%?tAyVpZ|IMEtlt3+9?9> z@s_w-Ti$0{@w)G2=6>DxWg3gU$8MSG_}SO#Z+XtUd39gU^V9u0&JNcn`(p?{$D>pB zokcJI=`4GApO%kV|38B$>^$en`JWF@{@-opKGq+HW!`ITGafgt2!5Z@x!?O88|=r= zWU}60``){?`94Q+i7)=Odo{&HQ%4+f67EvzE`7iyDM^K(pe5X3z(^(BVRo0d^k8YI z33k9xmV$`j8ba7qo13cco4WI3o4nq0KWtC8-FJJRXFL1fK6h{K<^on#$?3!t`t(K% zW0Cp10x32Tj=3kN$|=xLckc$+5jS(yKL{AK?5>r!Sj9STo(Jlkm=GoFggodvnq-C4T#5a&vCS%vEQf2JYH47HiQkM2eF^ zb8JT!pN2=Z%s)<0(4_{AZ%EuCGs4>4q*s(RIvu$g6=m(7MR`o&`}h&iV*^&5u8bn5 z_#cI4#szlcnLu4rv|3?*Y4f9R6W^h(c}h2{#W%in1M$RTcrqxRG>s`C)6$FrVsPyf znPrVRJ%O&0(9>M`laROH+^Lu!8JeIg6YHx!@dW6dnt*oZKoRopuv1QcL_Ad{Xk%nXAi)6UL6_L?|c0z&6p)a&H1U`adv zCSmXw!lcz5|6u7h%nm!5$4SYTTQh{`bE)v0J9Q|z!L5aa3{b@yr29z2C zPa9$k_Hw#LLC*83|FYUWGf0wndPdfVMySL5P0=E$`~k6-yL{}6)&k0254pwOi#xrh zxDTXfJ7UhsSpqfXN+xjRF(h{ysHRG}acPHQX}I+pfVxByt+FnJFQ&LP>%sI$C%VS7 zM&e7-JwS-i*V%hmSH_c(NQJQ_L62nCABv~`9IOyj^(nh^3`7@ir| zoyPgd-&q-;=ivyA!xGpKwV=Z)R}Xi*uhbHna1%NlaQiwMgtXpOpdzRjdcskZ z?#YdMo)vVw&`|7y@l8*UCBu?mqEE}7H^4Vtp$LoLj)%Z8(XGsT|46h!DBUseLE%~B z@Tv@gHx1O&_As7(%oq_8C-zAapHUI+EtxG9h_oi04x#N2CQNA#+?995WtLqc;b1i? z)@j6L1g(_0dNsUNN(tj$b#$di6LXEDIHlj4E4c|p$#H{L;xTC4)O)dyAcpqz@?VfZ zX@(b_k+xi&$q&Wwuj6}qJqje$=c=2NYKd#q)&h(CrXYTxl{YTZ5yi={COI_Tn@V5gH*7N6D@jC&L|eqj)^y46Hb?5`gcVGG z#ij0SaeWK-C)d0JX+G%>q3va>O``1^YQF*uFxD>;#5&@O?U+AchD#qv0cqGEk-Y=r zc=i*sPZuq3=l$fUQSb|`Nfb{TJl&0nXD4)5Y7;(cbR>MKr{|Kxl*R7WH?b7z={2FVuDeys zEauE7j_&=<3CQCS^=l;;LG5e^Js-f?2gNQs5H`D-c%$m1YDJaa=h%Z^Y^!_lq1$(@ zcas+pk#VT~un*&6mgNq=;6!UkIIYg?wOZ(Gi?6u6gvb#aQ9=|ZeJ5z$bw=nVZIzN8 zq%7Qa(QN!P`J{a$7UW*|?$B3IL<>#CAh=L^mjs834vBfn+jAda!>N-`jHgWkH<}cJk`_`YzE#tJyCrO)_%5MDtm=`6b`N(UEtB{bjM(a=(Yw zC)E$YDT2t{p4LWA-S4k#gsE}vA9dpd1SMpGATpzDl%d{#Awd0+&C=gpHS+}OP1 zC?KF^(V#te_kH38z*shS+@ZIu$m4;A8#d2w>z3G7W7-N_y5ZpHebP=B zZ>*fnyT;u8!I3x6lRDIOg+gYv`l9#D~Et04{AKl3jV&s6?iNw;=Ariyj~ z=#Xh_Li%~MdeBRjDOtoV_F;i&&&a#Ew6zh@^3@jdHrnsP5mf3(xnf~aW}(V0Q#s1$ z1lX|<%k5ENMV2c>;9WDeH4iQE#kA=}uMm1tXs|SWHz>vBNIUT^JU*4dS$UrN@>OCGPmL{6jW zbd31|zz zpG=(9G|d%r^VEwFkC%{*BipdGLQ*Lwg(P+FPRGN{ZTGeirXtSJae0L1S!mrcksi+? z#IjW5SFprb( zw`zn3k(g3G27x`YKK#)I$V99QfdaUaj{DJOk~X-%j?Uf3HM-$LB75 zz0(ZD`8ocrRKVYxF-N_k-)pvtu^5)hoYfm0%QQfRZCOQ*uKcbF?xNIbW60ZHqs%~^LO}-4k>TRNa9bmkw(<=b2k zW;G_7tmJT0?89mols8laEM3ZA-~rv1B=awCm0XspB+1$Ym18L4h~OgB6F7Os8< zN!g4n+D&x`_&mlu&|Fr3eJ1HxUFWf{0S3hJXkXO6Vm> z?4X;P-2eeXdE@t6@2&R-S&J!m&b{ZHz4tkpnLInZhk)~a z4Q|k7%86Mw^Bbx7vdsM{IVkPxvm4VY!xY=Wf{qzC?`N)0zaOGoSgEW1Bf>-w$Xg%c zkZCQIXgg86$Ki|B5mA;O>>e;$_$Hy>hdv3%Tra3Iqn-Wg;-x?5%}`$y-?Lo%jlV5f zYsro~U-u<#Jqv_7+LB1iu~~9{0##gl`5nVeXHlmgR6VD@4ktoaG;njn(ivCI^v;gd zTfW$xoU=n=KH14tESn!symBHEFGkGyQf&mIu|zWV$op*_j0`2{=qDYGU_04fR% zOj5oweVeg7)Mm2%szJbjTtoB)^{Uj}n0`T2o#q9vVmjygjIpvCEpLfd{4An^{mMtw z%6*UM7$n?+rZ)t9pWTuMRsT#Rf4=?n@BAA+h_}c$$>`s3Z?C~R&X+#EFn;s-< z&CjKW5Mr{cF24nWH$8p(0<1KoDfM-4LT}eUFg4+m$WM<)UDsdHYKV#5uKwzM=|Mip z5$PLfV|!lG<@p70le#MRsQmcf%ilrjJlIMX=@_992hPiUNZyt&xD3QNRW%6R z+E?)rkIdZgx? zegFSa;lk_qGX(RRG;4aRlvL``G`Dxfh~Pd)sFvxb?EG$fyp z33~iYn|J;ISO>ymI^=evkc!A9E8lj`)6rY)TYZ?kL(8HP;p^2tI}AF!~rQ8t%v zUJNpD8S*bk@#N~5U>!=6JF^wUogy-=C?-?WCjqMR4`?8ZkAmahM>maMGrM3TK{*kk z+xG`MkLZVHOJ-20cWio%`Zi8gd<12tqnbMl{}%H-iq>!#efzaQS!O5^PH@%KmrZY} zK)h@27eQaqk?kq>8p57^y> zyzNXVr2_(Ai5g_9g?uQuGCwa6#5MKob}0OBxxLAsPlWgS8JB;$RzEiG@%kZc&dLbh zuQx;vZ@l+yu?;2nO~~7#L*r7)`g(h^9k`_|K}5C ziF?`W*2_uXtsW?=h~KXdo*o|>aXxfveA`A-RxR%%eKW4r1Y%y-J}wb7D*3{OX)f#r z#=KO2{FeS>%e)3n&HDOm2H_uu>m47=qMMv~=OYtp9Y5F9I99CDF4HXCw28`+?J*BP zbs5T7-J&1MW^WUhPn`A^&6d(wOY)z&t1x?&fyLj8)xy|1B$ybH7FfFE^g`jsY|@J! zH)Aov>->cHe6Nw1@A(P0lPc8xcpClHEYUN5u^1sbkC!nPuUGKDfEzs4yRB=@Ze+D3 z6iL*T1?(ulSJ2jb_Z)hgXV-bgHNyB-pa6wy=)tJb4bl|-=v}{A>b(hL+nMc{P7A-g z_IcBRvxt&#A=(FT7*`);afJI6WOx>R?9tiqnP`mtStsLVhNlv4Y|;;ZpwugMC+nwQ zjojRMg9CwkZE*_+a?!8#SpxsQf$nvd4zhgVjNgY3Z8D#VR<%~~vDDZ5*F-vKvmdk8 zgpK>toipFJxqgNA%JGG=vrBnMY$^M)DJ7Pa+#BQ%zlaE@>UR#lanXgZY}@aAhxk8cGZ95HTxVP!uwkMf%U(mu46l1-G0 ztNp!RppjJjq9SN6$KAD`S0REPyYMu8z3@Pb*TYi7a=uM)=40THu9j;@2c+gRvO-~B zpv**Ui~3Rh=|?8ZA)T3Rdr(D=X7StcI-d%|*SRq|AHO&Y3R~wp-jFV9C2WH%==!aQ1dF7(Y~Rqnq%cwUn32Cv zO)28#j`@W!K!xRqb*s(*OzJ&<>0RCdiMa~CtX*m-SIM38aNwXgbfqgA1| zSj#U^I&=1|hP0bXOeKlvo95p!G6u9*3H5VJF3va3$5p1a=A5UE z(^4v}d?g<`)5x*p-{#%YA?((+D)m)w{_@*{v&(N=FBM80;G_?}4!k}#6uEj1TOz@U zx)6AlVT6G%UJWPb8ZVzqTKzt1Z#Nf~Z5kUJTmAF->t9c-*`&Ys_+IBI7b;No7`WqV zB-+d5IK%KuO4zN4!l~{2UcWw*W8Ix#s1tC5N9yKbqBzf~AQ(mp_lg=0FPU3VZmG^49 z{WUA7;`j#F`!B;4@0gl=%#FU~Jea9HYF6y~$ypBn_~^Uq_eE;l%Td-|ZZkyo!QK}h zLtE3kLn^hJbR5b8jW9vp%eni$+ugZbLPvN5Mz8C%A6U<6)=&nv{Z5U4AJ(_jq0Q>I zXz%z9k7JKAAJ9HL_GYGw^5I=G9|5=d70X-@j=OOE;{9_L7V9(vqL=>Oar9uv$;s&o zl>%QHRi5QDm)}fFwpcLJNx+`yeSY;(qr!^0D;VL8?jnb>BZxfoG_#lqWsW$I{iWse zW07h!iBjKkwVvr`b4J^y`4))ZwYjNiXxB?oeC|Z}^jYmB=4Ia-N9gv5*5eYSiu4h! z>q2bb(Gn9q%cSwcuowe66%{N}Z7q27V2yQ8RUej_` z>8$2&$xuL}tre`fAhiuS@~i9IS2#o~`@_Z?(D$L%_lTTqV{d&>=6{8&v?MVvqyI#% zotL#QeV&hFHt00TnNeWjH+;4Dm;WI572yYzNf+o!9{f4}6f9@8Yt?q7U2;lrnV-(0 z`_X-sl0EdSW5JijfzMR_*KzXlw-_Ea%KVd5x-W6RE#gt1Aym|djqfKK{0t)c_k@U+ z&I$KF=g|uJf9+1{-6_xZG7-&zGAuPIgQB4Cv=xf#eq7hGm=!<%d*PDuy#QE|(s0{r zlbFB-F>jDc7vpWb2URYkZhZ0Et>cx3M%$jvZ%zAQcDF!vGQ(2(uIt3LqUq<#b?60N zq<5csv+o_hK$1M2fk*I|nTUp**0G=FLv6Nu*JGA&G^l5{XgG%yzwCIwN_dd|H_Lw) zrp-sDy_E0Izsf|YM#{*Qk3Gx2nyz-gOMH|3okMl%_|fT$*_Ux_R8!0k4K7}~cJACc z+H?AuR!?l9j1%R@=gvKgx^PYy*y`@;DCGe|_#hlSoE*HJWF)1fbm4FpcbMcuZ#V+( z=<6)$>Eu{Lph8^J1BdSvT#2Az-rO|ur01gD++=Ep4cy~UnsV^61pfS)Qo0GgmP{%k zbEkU`glry9s|1oIw}w-X8g+t$g3=_WGC#9D#S#N}_Sj5y_P)X%k$!3+|6c z)Ahc7PpN(cw(oqFGW58y2w{BaW69vFv~^&LJqHpA#3_lB*wp9NRLk$lNcMgg z=H5+5gz(s<`tLu0E3G5Eo5>2gI)UHH#s*7%!(f6Yqf7Fns$wBh3Vun}uKk#r6pNP) z{H$#MT`tNzI3sQA02422+KWd3sEH9!jq+uKaK@R_%Kyx4LNvs zvn&aQABA9gkAW96nv98lp zMs*xBkkEKy*JF|(WVl(9#Eut%pnCte5%-9cQT4l-nuNuR$e=obWx(OnkI;eCNI7^% zvl{6TZ!QBEsYI%&8dlYHmxH$hmMh`2A()P1bRlOauv8{A<_z-Lk9Exn28kL z@Vr1+vOhbJe$h0y-{q8>^cK(BZAz-y`Q5BeGQ+z_+jSi)lXUUvxTT#gbCNS&MF!Oy zqC`@`qhyTV-1#{qG`k}U?+cM9b>k~!kZr1AclVKZ<)r!nGuwd)&2%0sl1A}oP6fB_ z{G_M;6ezM7nse3>B1^LVH$p+&Qri8WYtq07%A{z#u{5Sl)!R`nHQnN8qHM+Ykn5xY zd_80acg%;!$nD2nk-VsCPd0G3Yycg`A!EMhQjYO%*r768f_V1a zRn^#fX)ik16*H{x72FtpQw5q-%~M?+6`bJQi-dox@7+NGFl{q)Jl0 z+ei^SI&Y*JC$gi^97Em)wd&41>S@TiB_Rtw1zV4adwq zX^u?YxfRy_tT@vPLie#RK9gveUS{G=+ob6eoRUm+v$hW7eIMcpBZb!!X@G zy3Ad~(1y3T^p<$@X=LyYJb-!TgPkSJ5ueaqDJG8tD_(G!m1Tvgwt?L7B3vZULWZ~}uSYi_fL3aru~|wOQQ&YV5GIU|r>f+PvFGE7 zVcot~fKxfpX7IFiEWg~tq{y8*r;zl>Bo`#^!2L8l6>?7qMqT=neuq=NeYw3SpuG>d zoB3Ujt5hOJlQSu~QiZAGa|2WTyoYMa=r&uJwlNHL0Ur}B&AH|v>n zW`h|frRqT#o!eC{I1Qjer7syPsrgz0aWN~2( z`Xb8epwAOdzjLk?_iMFB&+(CqH{;UTY378|b#fY3DVBL#D69>>Y;FpoXSMe>j2)Ne zV{ezSuryrz-4S!ZqG7*l)$_;VvX-Z6YZo);V{4@=xLMO?GhLMg z)$=EZ$zYZ??}oGIKJmXuq7rsnQ0w^J9CV;sDBFo=9CyUnDI-D5D9`#7jmc7sA2bwK&E^nd8ih zM0+U|w5uF&g-(k87oNUVvilt-iuC4l9;%W4+j2*B=G6B3ki_(>7ppFru~sYldeMX1 z4FZ^D5f2yJE?7`UR)OU^{Wudsy=YUg@rtY*vzMnLXtpmEbfN<|Q1jx)aRn**NXXlC zh9O6GeDX_2zmiLS?M(;gP5mC#b>`-LsrCkgu_^~t)&3@CT_cLD%#MWe9#{h%`MtNXZZz2k}YLu&E`JmM7bE zr;Ek=Z14YP%+u6KFFtT*wWG(9jQUly5+CFN92UABPN~c9}?QJDQM?6;@kvs|XJG7^~y=U*%Bhfq87kS^6M!oR5 zyxDHOEPyF5TPeC`tuhYbW4}77SX{*~-}aCvA>E74mTgkGidxjvQL;4Vz2Z4t;^U`r zZeAkbPWk{2yIGecWsBS^LynRXF`1Q;bsZjxw77Z0rwQC%QUx922M^tsn%O5+_#neq zU~D|$gS_?kbcKj7cJo_Y{Qtl( z02HbtS_tJY4OiQCc`7vGCpi}ylGyhQ<}Hz&se|rSU|IVPHLG)+rlFam<%zZ4raR@G zaVSD%K%~`$JMlT(iBKhm_LwmiW@rbb=UNV%F7X~7VrF@XgD9yQRkE$x+UZWrIIO&B z)&*ETY0rFoUYDqy7i-|fxY>3w$D`R>I;G?DGKB*M1)@oM_!7)WB2K7MRlfc7Kp>?Z zq{wGZbZ$;PWz9UF!{jz+|1^GbyTHQS7PcU}h#GK7li|X)U;7{8BtEEO-R}|#V3#6Z zG?ccqWKnUnt176z#5@ZNd5MxH zLksFPsO)-Dq?dAeJ8yuF`*rfC=I_T4V7^3!B$WrbARp)riRc$zoGIP84NS)K0wDtO z2o@uAzs^=gPThHR)tE5Z3|JNQX&mb|wR&5QY-V@mprNmwZ@13h^^CF{a>sc^2HY&q zRQM#|^)84J=J~D~(l!g%~Ci zcjT$hN=rrRJj>?VER8-#Q ztHh&4?4Sj!wF5x2KAsRT?tWtCe<6a%VI(;Wbf<(+#s6He6nB$_$J$gWFahbU&>Z2v z&3sIA8vi=`Ce-1PVd6LGDTyc+Pz~u`2c396B3y!yr)_DNa$~DI#apdKu zry$mJdoFF#LPOVCUa~{s(1Szu=$jm%eS$Qu`Lnl zjuRmAHw_YRErh-=?P|VS*Tpo(NCR9incj=h1G{!W6{;XcbhIsvZrRp-8iDp?-Rz1C zVCS2o4~cy(FAB9+FHKIax|q^E9Kclpc&sMZy6qr`K^Cf48a`YJsl!$^a48VOniJKn zGghP(M!JCXQ*mVGiIDYFm&E;Spx<&VDpPefOp30$!PJKGWb^3A54d7H52V4?HkzDO zU!_nfE#H;JnUL-&a2iuTP;CQZBs#JfMk-bD#Mtw?$Mbrz{5yvM6#zdphnX>SQIB0v zvG-q3Ed)R!<{zweiExI-%78z1JQ}+YJEuJrr?P#npv@Rkq3y?K};g{MU^;H zTVMkXd~S==EnDWs$2NwXiw2H1?g=ldM3~y{{bv(EtA65%_EhWF7rh#ZA;9RKvYTBO z11|If$|})#2hbe-VA$=X#23Hd6~sT8q*NJpQcVsU$?+;f`^Xq5c<#>Aq~M*K1vr=G z`c!M|Q;Umlp~34hC!V*$u=goI5JEm;c`VNL+DnggI*&1FRY@_m4=7%BnSb;&@}JQF z$MGR??`bk3apEZ1v$zvxF+Rt)T0I3he=5JK%j5RP7)SqOHvxSlL)(AhY{JmdV?odD z@ZV)_D(ij|l<(MY;3M)8trTfPQ^o(U{@L%)Q>5pZmkOZ5e3+rzq#{AJc)~U2f~Hb{ zT(WKBKDajH@F$(8CFhE%z1e!~KRuhGK@^)xcG+f`#v$!9Onb(1czhg1OXGYi>HNCD zikEbWxAS7fy#zM93j@G>^TEe45MyyxAR8j60NTb1|KsONDL8H9lRn%+14t!*j<$=h zUrfaQ3r3V1>b9N)gxoPGd(LVqp5`AX(j4%lqfE`(o{w?jh<+g{e2`Ii&%6bbRwdJZ z2UWv`QKE-x($corbT`KV6EKTF*o(YySx>s@&OaOh98eC`aQ|((e@g0*f9oke_Ffgg z84fT)W1chbCCN+91FIpuA(Z07(52qMg_;ZAT7~t!vS8(QG+0mmztNgXoY}st-lZWu z#Maj`#-KvvSB-@LVhnfmpLcm)rUTynpO=`IpAuVA=^(e9yYEQEKdF?jYb#J>Ig9Y| zWc+VIDxj@v&4vHa^pk>O;e18Fr6Izfxb7>ZkpR-|@M7fDJu|WcI;mZHf{$F zo`^y(E(_?BBpm3aAf&eVE!ajK`q=N)n)MIU1v`n70W@ zsMr?327Qr;Y#-xna^&Ml8Sanb;> zilyX!$e!D@Kn^#sFs0G&$2ekVpG~DG?A&O@9>5jfI%v7avU*bg7nA;TUd?gL+e)q7 zQp=RAY7n&p%sm1)LwA|HJhZ0N4B4O#{GN_Ib?B5o2_eIsN~E(!a>D`>>@8Gc*kU0a2rN zWOa`W^9{zI&tKr{x67^!&N5%90vnC;_fPY=~S%h)BIWz|L58UH!RSE33nKWGW zpA~J6XWo%J3Nry@GCl@SG)(OPs`h_4L*>2jypqx_aA4jXr?3NR#lksB;;0M%m6fG0 ziJoG8-9ioLk=+6TAQS*330|$DLyiEZ>W|S{J1DHj3hYQJ(r^#~REXWVz38X9`sv>! zp}`p&o_qz^QuUsoF@{Npn@pYK4YcO-I?YM&ZCRb1f?65HvhzNFg9ewcQsTc`Ls)8v;OeoL_H55WJ9V2LQ9D%F_T zkgD)%hKt7;#hw!2j%OwrAc#g*JNp>lOdM6dl;gW}p)WED)Q)i$-(8~bcry-izy zB?T~U%>&WSHz4%}C%S$BJ^x?9C|9X2-&r@NB{9E?b5-OppH-d`WA|m6y?7jFgn(V! z!#6eBu3s>(=bueSGK=wh*8LfhYRk2Cc;4`{!6 zB!%ryUeemtEu!_YM3!&Jyy)mWV@SB&fK=-sU$vvHL0rK|e9=oWrTd2>H^-dvR17AOEr05K&mABKD-$e!xW-3%UP@t&%opVpe=T!fxU(jQ z$_IKqt1H2Rca6yG2y@{y>WXf-TRLCb`S#%4%&f?+pqWnh7_bh&qFvR>3p!vk5HK8_{~?aE^;I6%fkChlBV)O%kF$ON9v_S9v)&q=ADAyVw^jbq>@2MwMC zjXA;paci4_L|E`=G@1an#e`!p0?NuxMym@ zvja;i0}rymPd{R6)!IN})+{O-b5EyI?S5$#%H$rLVD@`D_Wx^UNRRx(NS+mylf7=kH=Z$ z?Xa~Y^JY*AxGqnwPSvrO25PX5e{R5U7@aHAg#I?h5+@{kMnbCLYbK@LO{!w|D|5yramt6o0i9 zxHD*cy3O)MnY_2WwKbQDih#S)6^C9rHv`k9yxQV#K5`vdDp%`N<0}_nQMdR?Z~Zm? z<2`QuK^s`kjx6n~bwvr4LZ(r-zVW-$B~=y|)e5DW-pJN1-6!~k)$=$QtkGI4>y8bI zcVuZ^txHO%ggHjtk`-{bfg=?fwiw#35|v(A|4*8Ih>{rI`|tgHXp+wQgFguy%JlG)c??Rzx#&cn2>HY z?1B+TuQCZ}s&%#mT!V)p?Y=IQxzoKxF3P9}W(-Ih6;uxYHTs|mhQJQ8E*nwjo=MrY z8||xttHk7i$g^N*!e6SB=rTQE8d`cXa`k70n2~~;LEMmeUDQvSrM)GjwVbWpA2Bzngb0_ zc&8UjUkAV}e9*slU_tmuf+tA5&3tDz|^y=wCmz`$YqX@!W%B6`)nx(UW8G zA60e90eyvpn^34pX@YN+XkB*!5HA3@rQ&w@)v>9|qF;7#=Oj`IRT?QBF8~?IZYtdF zZNc}SaF6^~#P|ZevbmXUFrX1Q%Nk@Pv#^q5+_7`Q&G9A%H(4EBOQVx3+59>n4OITb z|E~svW<18?e&>LEh!3a!>D#01M`m3PidX+tQIFqD;tq1oqyJTm8$bmLRE*4{bMmTD z96Labk9h|Nf!UZks}xx)pdHs?a_&i_h$$aR1vUf&(eS{ZIpZrhNh;W5y;mpWCz2gm z6<6yHGHdG(bjMh(I2h=Uv*?|gr*xch2%NwUdT7^f%J5sSg^dJVLl?%>7U;^BqaNxY z*8W0DQ(S!|*7lFf_Qpnnc-+*=Yr*|isqiw9E1k;OlTW3-dGM`h%a{wiKYBcr-EZ$3 z1h1y~u!aL)?;q=LIMa40<8zy@9LY9j83~#ZVRUP$Nc;9PRIq-;)PkHnXk`pTn1DVP z7jmX*Bo7EV6=kM;QF)n!(4q0(g#Z6_MSTwq-AjMCfMsecaDX zDjkF*t+^BuPIB}8P)Mdi^pEeNY^MHZdv9WE)#ZJF4|Wn~zIiuDovwWT4^_w(+Gd;i3fF()YtOt(>!7k|!9367VG=53y(9umd=~{l=jP)R=nc$b- z9FuDrW(Y{S!d^7)P7|dmW4O3X66$+pW3&J3NRX0Si|R&e7+Y!iGhd+zHTB4{$qILb z4CqPGJcyT{cV_v^ARR))9G8T+3vFpcgb&CSv4T=dJ`UHGmcQ`jMXwER?pUPyZB?`) z90`F=w_h1Ks!qoY>LvFoq!~F+g+bA8EeO9?ookvj-dYnPfCGyW-o%}nG$V)7`Ya>Y zsW9#d8@PCW&$8d(=VTA5e5|6avIXI_AD^AbL`#^8ek7fS+zJO+%;vsHcv8`2x z#!x3jb)(9LItpw?zCB^rLQ}Rzu4_yk4s|7yYETFr;yxv|_Eh3nQ#sx16m+L4oA24) z^@$ctyBYI)!im!FRlc%G?nU{fhB=Smv(Znk;c&# zpS8YQ(2oe)LKnRyg`hfwCh^Fp=wfn#xXt(Fz`^L`Q_IG<0a9@ySIeEooB{gcMDCXR zjZr&?7>mZDs#fjBi~)mU1MX})VH+KPeNb<4B%&m%>TYA{W{phPYe|=>Y5kSIIu&W< z_Pftl5_BqFmpk#m-CW71qk1%JMq*I4jRFn%`{wfHn1R&?HI%S1_dRxW{ov+dSW~lx z7&mT<3ADK2U$qJDZ*nE?Y`rH;P8u|AErr%l0?5|&{%wt?nrla~rE7eCEYbd|Al+x= zlb{SgDP)o#e5+wV&nZt@8J(1_!y%*mep;iX2+diKoLH8SIem_xDWvaJ&ECASGM_@G ze3Kn~lDs9-Ke)MZlI&-f>QfVZhWTM)I;_~*&mC&(FXy^9MqVwKENeBlMmNPE-r-Bu z%0&q}i^H&|ugZ(z@RrSqqkZ<}@Ci ztyk9+MhN;=yehfAKoA!8^VK`mKx``}zk)}~5cQcxp9@kq{RTmMhl?qQ;LyXWMwR;< zuL9p~rmP+e;D&5gjE?>m`}&*V(CP)7dj60;U2<{Lsw6*A(_-yp@0H(-T|dm&SFX<( z`D^otexl_J!)>F7H7Jz*5dcFtf+~{x91xFj6w(~`%EQ`nJ5+s56Y@;6X)D&>!-spT z(`svr*@MItRzz4L#rw?|qmm^>iHVcVi%2eBJFIzqpm9j`2yZ_*bp~3SIJf>RK%tSxC3cpIW^(vS(_Q-_scK+)XWc*fm*F zNFX1CN95Oty%qcTrK^R%}Gpny} zj2z}|**Fbrx7u>|YGpVS*VNV%YkOB`^itk&YznSmB< zt9*r_HCr)4I}k-apLV}ilB#hVMXOWgquB-+uV&2Ifk{wwYe*=lv&fuF?P*Z$<^>s@ z`xSJ-Cx2334|4m$Ga>pxK4bl?jrI4@qpgvfWrHxMX>IJYm5rmn+`e1CmLgAO!qTQc zk4~;m3-P||M?s7HV?%8Nn_F~|n0y_w?a4{d-Ic0A%I<>J)MAU3Avx@XLSh&s7BO?q zq^6SpFuLup*a10?y3>SP0-m)fG4g)v^Vex5(gD>EhVu=~%#;kR=@wIZj-!%92XT7~ zG;8WN2z@)JVIg03^;*;)lU-N-9xV;I4kCxw5`BRurNw;q-WX=9!$Z#0I#+XbboT-% z9}wavAuf7$GOcz651N*Gl?Jn0e){CC$)og0MHS1E%RBpWEBPTBn;UC`%)691mlba8 z(oo2XwZko>#H%nTo__jbzO@wKADPCA<0^}z_??qomO@-$>lWlM?$L@1wx8GwOu`O4 z5_DEB-B^@bfA$Kz`H8Z>Z*UUECrsp6QE-?+1~i}82BCHzfy9e7R`>QBH9q%ioCKKZ zAxGBU`XYyyN|YKgfiqI7F~fr?x@YQl!82UOk6p6)A^u33 zsl_~>haVS@ZcNx{xIb*66@c?b)uJshB4QM05M~@r0f(u&?8$z z3CgQIf}5da8^Z?%b}3|qmHXI*e(TWo)x?6kbG$adt*IxfE$(G@RYw3=m$rH!{6Gpt zp=z6393J|*BQ_S;Tdo?Z!C@HQkt5P+3gTKSWoBkeUw5xzt3P;fKy?#2(<;SFAfC3) zzC`T*E0Q5&zAlHE3Ml}ASJ@D ze+gMXVrO;IvpQ;qsXBULvDROWypJO_pz61Zh}@L57R23D3TcT3tueT{b`tNW0arJm z;p`_T4y?eA^_o!Tc4d2TGZpojdfan9v;ZjIFs1^*4@GKc8M&+SX`l-av>CU?WIk}^ z-_yBW$oe_d9-$9{gy={4yVf!nr3Xx*bfKVpqZrJZrL^h`k*YV z?sC>^bLHHf!_5BWyE1lM0R6u61+@}=H46?JBf-xDHl7&t21K;+RT$EO>x3vC# z;o%m(={+bk+&XAu+n8{ASlf)C3O(s~jtWva-m7?qFd$?Wo$U78Wfn#51>N>#05%_+ zjlbCUVk@Nd(n1xW}azyS(>O=8J*(sG5lmWvhyw{h|p<;G7gHWKc(C;Bg-^?N}3)d_)^f&2tTsj z%=UhP#t|s=`|{@_%EIZO+U}79L9MuCWseVF_PsAM)c46F`Hy*_>g|ntGaP^Y4i5b) z5q!iWt)$IAUMk_F!g`9nf_x)t*Kw~UYV&juvj!GBiEM3om|9PBe`$7ad;iV~ZZ(*f z5Lsjp+;ZSI7It$}aY7@jpNngkWKhR6{L zcQ;@IYF5gx)u)B^&IEb=!g3_ku!`Uk&K6^`#Y)8L-iVr!a@X?CVA=3m8AWO^GO6IY zn%0@>?I%GWsx(SK`H!%O6+JA)HD*9l2RBR!244AFTfPO)8h9z=JhZu{gez$TWOdFO zk$bvTX3_GbdNM?~kNkO?u*VUga!hi3KiTZUZn>7|N)E7|mq*PRB-;u?a|a5YB*>yW z1d`1^ooAO+E($Fk$b^*wrAF1ns+?IxZBRa7(6s%Y4qCyoWqkRQOr1r`aO1H&y59Qa zf3UqLiT1Z{iS@IqXc;+DN0Y6yHS7_0K{TC{lv5?AmV($$>$6aaLTHcT^D@5bqXyqY zR`uGBNjt1wAv&u5NM&RCY&uv!D52))xd5?d_pvd4d+Y4<`5p)!tAVN>IhrX|U)tCv zcfxfleyjZ?_E+VZkP$1cLCAvaf*WP6i)#h9@;i45;8OSdht~+Or?(rcHc`cgP0Ni- z1~}j5rMCuy^t%h`KN{9IwsFYrRkWF1^-<$M54YJ&jU=*n+0JQ7KBy&0WtvF?LnwyE zo`tOy)OU_<4S97STLbI?LSSy;Jq-YV`>7u2zDreqXzBiS^WNZJ63b-4eJLROL;vOU zp<4Bkf1&vI0HY@IS?s`1ShKY9=Ohd_!47LsuM}eoQoDzBn+QFHm*Pkxt4PkWX|}D9 z)fj&<&{hj?SnH8Jf)B(O%B5_8p!_&++ImF-E@P>#=PMlf9Ycd-hEKH~fXn=`Rr zCveLFtMem`6}8~;Ws6k^r;Vl!Zh7@N-+d`L52-ix1k9EbLao*~x%`&E$6Xo1li|>y z$rG}ZPPQq|qUd9vH*qfsieRs0E;i@HX{i>v^u|e@ByL^-(G{7mrico>ALw?v^!+5( zR|XXSjJ&7kzAK!XH&nJ)q=S1>?@%V9&=?hzoD3Eb5Zc(Bd2CklkuWNiTw5@*iZCmw zFGsao^#k~?E9|CLJ#1Op>rzZ0ioP8{54$aIY?Ex5R-Rxt7K#Xyy|7))J+O38YLe<8 z+L!Ou>(R+g3|Z!=HR*WJEs0ohZlhJ53Mhf;Yewin`Nld9@K_|6ZKsYxE-RJPX`)~n zYHd5Lq+H9gKM!~wpv{;_;dCL&o~wD9Y$6>s)d+o2Sl&zEd zV{ZUb>2`)6xj%JqGPxh)pu>>{nOeQ7qmT}HbYxC|CZ#L}Ad%AgL9w=}Qcy&|8U}Uk zvqON0X}xAs#g;{3@OMs^veXg+ktj8CbZLTc#+qy-0Zpq_&-JsL5e1N?;5p(EXsF1a zYZPVFRMF2+$l8;m*EEU}YBBKl22}&r_&g(@E)8y;zR_*!C%Y8Je$RoINxdVS)c&%v z({5VI?$&X6T@~er+Iob}9@sp!_CVNz#FP3Y0Ch>g?wJp6lI&mz9S}Mhc;{yFF1T=X zaC2`I#CsDODtL&zF{)-qR$rl(>6d~=?uHR};6;Q{m-OMc$zU`k9N`X>tvl>1kyz5? z^IdyFZ1He#Mc$^s;P~#L)7#yF$}Nqu@={7pO$9!2SzWSh|3!Gx#-K1NpG;mo(idQF6e z8e4=8HlB*skJFU6l23Nb3+cZr3WQEKv{cswhn)Rfj*#h#252@cz14ndI&h-plnSWR z69+kxNxec71itL#O(6};)2fjQV4<6x%j`-BCti_${Zb09WZ)e&NAeq+7?m2z!B*qX z;Msy*A>t7k*rD-`Ko~2rVf*>Q=E}}avIdNO z?Xu05vfLZt_u+#$pT{%b`yN1%I)#KKR>CT$8Sb`n;)FAy05gU1*iuUOOD$0ZAgI$S zRkvvicTf|IqQEO<_w1v4gSf6YJ z#H#T<;Jn{wPFu~yBC#~ZQ)i#+OZZnleI{ek(Lzf%XJah=?EPKxbE((`>Gjii{yesu_Pf_Ro`8hdxOdls;sm4750WLwO`ovRf+Ig)-%p#PC(}^sILwuP zpM{7RRv*d&oB6}1S5J8=^dpugLLcvo*{AqFfmKj19--;W4IXKYyNQ(xan6W5+E?ze z<-n6njXlNFjv|^~-M)Sr`KjVY&YIh$#lOi^{`{_YLo7W_r6~%mQz=D(51aRj8#JEX zXb{yi=q|ff&puV~M^qYzNuJddd=Zaf*@nu>KM8&b!u$+1@${Gnbty2++{mSKKC_IVH#r>dQs@qp z*Oi|32TsI4*$<4^p@_D-3evZ!7DOj-yi~GH%nXg6FHXpQ85klZPVt7FvE?j5qi25z zR?rq0{T18s|InIgUk=Zl4HQIE_1_3gKFFFY7IbS{$FSo^Da!L(-GPl@{Lb`sMa)Lw z`rAv{!s8MRw|=lor@El$U)UFmKWRfwyR?&nl>xZv-YD)LCr7BbCCo!j)QSGET1N5PfLzOD9eC;C_d0 z-Hfx~o>TQ43i29$M^(7t;t!e#m2@7FQEN$b7D*n zzVnxR9@Rza07>K4>Ld6D!+gxf`(G+e^NCYLfKdb6+4RCn);X@(UGh28pz={gN;S~^ zaIsfs)(~kGUv0Xyc+`4jD(??-#9G=@;Z~Oh(2s2Uoz^>^p=lLyTZsX-z$vZNKF#H# z6yNrP(5pGby|S+}4?|e-Cln_9P9xP~Kq&L#&e@&gJHN@g(xd*?p3pQts?qD;w2mJ( z+a1y2PyO3@DuTN-5(5YvNn0A>O18|ICob&)cIOrY)E@2Q63Xly2Q+AMh-}vz*!AAc zQVVK!Vd9P=+Mn9R%{Kahq*FDL4qjKrMviOT^;Ao{Kab1^Y$sabihWzDy=btm*be*z|I)O zb9rnPU+q(3S@An!CF=|AQ!|$%#3w$iXI?X>_Bs0kSo#Do{W)+Q-}yTxc8t=a=D?w! zfGH0PGqLO|N9?HI@l>;pi@evo8mR6xa*pS)mL43IO~|CsRh2`P@0gVP5>sswR)*>KfhRQP4{za0`{W@QN1CjrGv>^%-Vhr!kM{ zyxckb4kzv6{~_zU!`b}ew>zk|irQ5pZEb2*)uyG2s#Uv2l%n?DBo(b)YHw-LYON@0 zREU&Nqf&cTh*dQrVnx=Q@9!P|yt%G(B^Ostp7T7<{rTMY{W;G$5iC!SkPzl~8Z7jW zX9*DrQbM1|(6hmCY&Tp8i;O7~y}H41C<=*$%gRGD3?aquu85Dw{4=`Hgy0|E$+$5h zj8%FnUq+)3!P3q2JRw4per#$5{e)T<*#0pcXCV1w<@3WU{CXue6Ux_zR|M&Ua-$!$ zYce7Ev@dR!rYhg6U8aIantr{MsalfwqI@YJ%P>V;x~x2+8oR-5YN6qXXHEfHYUtvh zpqjYQ)*AYF`V(u{W$!y=A0#9&bBJdPncm57dnc)l%tXC0CjRJidac4kwR6Zh;TtpJ zmwlvBb`YJA%8Ag4^6wE%?h$CVX2}<;*I!7F5DF|jLnUB|ccIQrWxN+9(slivP)C7XIjU@n1W;ONs#EPy&BxRM9q7lSkT|3*HG%m7#!1jDg8zy zJ%nNE$>9>T(m`98_RjduI(qTa5T@&n?TlHreM^EzS^RVm&^HPql`fHwuH{go<=70X@~%vU8l5l zEM3bI>iwn{tBJ(MzFw*q>7-MMOXG)|M}Bd5ej|3*ZLP5aVXM7`nNu8$1~b| zo9EgV<~z5JzryWP)zgiQWuTu(@oR{FvqMn{6U#Nn!LrH-m4Xd%yS)&O)}@dv_TIzS zGz0n8{96$m^lbh`#IyI11ucqyHLLBocQ4B$ng80ZF_tly9P3;LKs0*1YDZLbYtSlk zW7C|~e=!iqX^ixCKJ}R0c`>6eK9W{)W}OmT?yO!~d8%kPsm*x1E8|9+_5i^dAAJRz zP~No(!N)Qn{jzu&`?H5{_=&88#R@1Magm53Ch;J{zFSQqSm@uScL*fn z%&6+QG}$$TJrVJNd@Moh9Hbd5mBkKr0fwguF#6R*F!CV$uliKsBxvUcY47*7E6Er} zLX`UL2(1Bjq_^Rsu%B!nLCZD<@L*3}q@O|V2Juzfo8>x@e&jao!&0e;c#{2fKhq$N z;T`C?|9yO(ZnU?J(C2*^AlcrEW`_)mG9iMm@SthVcruI(t|H4x&{79!7V>Bu4yl2F z#zlg(d3~z#8F+<>I+Mpt^nuw>ftO_sgY*I}Wx*_oH4x^kn7X-+Pp4qVLmEFa?6eNc zF9lMzB6nHfJ3h|QoW9ZGy=WPbor9KrnmG|;PSuvAbx2WiXplj~yM4J@a;gNqKSaU4Ts_%Hf|fOi$k~^xBM(W?8VCO$JkJ#z z_oR4rT5`alN9aL_5reHYH`e+GLaJa3CKjQY3zI!Du7+I*^zH$$Pct-uWsvg&h%Kb^JZ{G(^VPVZ8sR?O(Z_ZxYx}dtzBykXVt}Pe?l@w4FgrF0SgWc3uP?^C!P zo`()fYd6fNlTg$=-Sb>=1B$AhEYpk7gpF_2q=CV7gy_5cCZ1&jn>)fULICQAXE3`e*21bfZ0-MKkZ} z?Wf7AC(j$Zx5#qwk)STFh5Xf&rCkvqdpP$> z$7T2bnE$QzM+?RWxbIkhE->>tvGc>WGB>#DByZ`F2qr!fuKg;KN~OpDj=F7aDUzUk z22I?G=1Bi3O?r!^xASzwnoS-zUB}2dm!b7j0G#2xRO@SB3jj>?0Dfkez;Cdinr0FC@r%>NWv04bQt`pyy9T}k7xi&5k$m?_lNPt9A_v26mL?f@+5yV*tc+(2} zTpsPuj?~-Mpua27^PU4S-;64n3zl31K0B;ROEI;R$Kgzn6$XRs#~jqP|Kj4FZB~kN zJ&YsJ|0}}gLKB!93CgPOjeSU~maMODyHGH#Z|ny9*w%tob6&)3K_a`h;^<8}`n;RJ zM1+Q+uzWx4D^`q-voF=K!ljE@>k#|~&DjYcgM@26i;IkH=JBaAm89JpMErk1LjwZ5ka@rjPpt$5YWHjz zoYL>RS4-gr7dVc2r_nbWP6*(J6HQ1XoB7cPNKNJyI=?M57hqaH>1D1r&AQPhWq1pJ zW*K*maFWGfBgQ97mnV1d_mO_`q>QTzuV0AZZ{TBBxaj(Xdw7Mu{Yge+RlKSe`f?wR zor}~h0MNE23(?~YpPq*8Nd`|EM);MgR-toxzb&?kG2?s_E!a679f7@hON;Y|hN?r# zi(9I3#$d7kn6VT&5{_nOy;1mS(A0(u!SZsW%``0Vw^2>p=u3pPJ!|AilSfv5QesNP zFBbmN9_fNWo}9ZHX*2p!H?typ(FOaamquK%s!)}Y8IR1{H%#Q=zj?4CJsT|Ioa%;{ zhmA=QuTMauF7h~-QIh^;r^h9?76G!tCYXEMv$}w$B9usDW`9kGZ_Q70Zvm_8hF~uB91hFHclmNOL|e5gK1(ccw%m<$Us#kU4Tj`(4ieU6@0# z0VVT@GsQIF*DrSm-KrdlFse$AC?tX~KT>QUkg0SXeYs<;p*Fah-0v()OI|7z*y3j+Vj-oQ2b2FcUTO zD<<~EHsY4w<5Tk<>0~As@DSFj7r!3GEbb(;>wk-3Lp+&FKqo7eZ%b9V09K_zkKOwm z2(fKqw*!zGkXo<;yf5D+_hI`D7q7L$!$5Nsii?*GSk&W}#o;UjHbl00xb~6r-1`n4 zRLM4~0)G9r0cW$SA;LS?r0Rvb?j)M3Hb$@n8exgON=eh#qdlZkr`hMDgH^MNdbd!A z)~S4<6Q4}tew}Q6-VbF|7XMN;IBm0VKL@5eW)>)H)kTj#DaBHLpW527JSq0&v1J+7 zbe7a?eN@#AFPncA+1Wy8ap|`fZ)}f3c(a;0HF7IsPb^(_fpqgNMI92U<-#3)E*PvH z->&W0y@09j<$u%3U$D`tUNDcNGovV}UC{_ZL)@O-lvtqCF}p)rrJUkOGw3d`STC9~ zzx9P?K#v z!q{T1N}9y%yohjO2-a|?pFg@Jh$_(|Cp4gW9Ex99X3)@br(pKc+LhaVSjweX=(@R1`AL2TEc9@1^Xu)}D9K0EPGWaTp!ONnwvqKqJ0v`gKxpLI(S^0(uL^4!$vkzK%p0PC+7R zj`}eR0g73Ny?~T0kMsCTffPRxElCitG5JKehsEF?9pirN3r+#g70c>+t57li=LzJ_ zkt@(0XD5t0J!Q-qlKH=ug(5Is>k-NY3i{FAaM1DPbj6tTwwyw=aV`Y9a)58{!dU6N2?tRvOJuaUq52~&0?xD^fq;=Sq_jQ_ zg5RICEft9XIA{+Jj$b>&VdgO@d z=*eIwL{S)q*UB4 z9|wU}vw^{&9f zwD3!GOA{FfFNlkSjOYFwt z&}I(ziM*CaI?i|!A5zaJ`Db>ImEiD+EWhE`BpvIQH*jny;S_hpdISfgRODm9*My=&PcJr^>HkFL#ck{2= zHXjtK+uq6P>}>3ph^D)hpSQmbF23ROZmU^x7x~kTrM#8GFb|W${jItH1=I8Q<$?b3 zNGwU%c@dT}F*GPxMcKE-*2XXj3eBy+yjeEq`Zp`c6pvB;XX9i9ti!L2R#uLmdI z4c9hiA`r>v3efTYmpUOk4c$3;@4|CluoldNlTVrNtw8zBp|)_gSEc=mK>Rrr^Bb^R zmR@xi${Bww{wlI7Ps-^64^2z7V48N>iYA=`q^AQrdPavop0$w%8Bex~m9r~AGw3vj z3gdLhc+t6(dUp6tQpR=JhXQ)=w21S8%lEqg^Aaa+J$lJK+wG#W4;`KigsN+@ z57NRt5{x+JgDJNMc(7xi;6{Pv%XfMoxNG`~%6f0R3gmrz+g7qn6@hWu$UD4wp&qE$ zGi?}l)#jdnu*$oG77_L2nro!1S&oowgD_4T?yYdshvPndn6szu51C!Gz+gcIiDHHI za4x{pn1^_CR6jTP+H<~pbp6mLP-=N(F-Xm9gjydpu^aZrbe34`Ky6~o@g6A%GxA4l zO$to9>%&PNR$Hp8;-n0lm;#Utd#E+=AVrs3Ut*+A1-NS9vWOut_aV%y2YIa=bOJq5 zCMa$$8*2ySKw}hLdD|=)1X`eExLU0jtOM0if?VNG7pwx=P?THZ?utk7xJ)^XuU$-W zkzm2vZBzO>`gb16Q#A|%?ivad99Q)Id}Epueu-7g@afU=U|H?9pBq53?VMo>){^dV zHvh~uZD1PSQgFmKrF24!vQD@%=y|yRV*TT+FA=raKsuFA%P7h1F*Xo;Mbs$cYEQ6T z06+Bmx%^zD35msIKP6{j+fz2;QBduRLVAtw+KQGLvh;c}1*)2D~BC*|ppbX)hdC{an&9QAj?>PzCjNz45}( z-UY0hODBJe@4L6Xp{S_YbL)o+`PvVs6nsEni8cv(%|{5w?e4${)Vp_U{V>`pfNNm7m!+5V-n*9t zMQYx1_M`Eu!MfeMy6EP%p9INRo&*+;I5QyQMiUxdAw8gzQEdq7_>f_KGh>jJzE3kG zVyx)y5qLLVwTrDAz6iMEiYD3xXbi~pzI_;*(d~e7MGpMs`nnf>Rry|t3C9_C+I^(3 z0VJt7X(QPgd9#I%K%HF8E5j5P-i0g?ompX|0M3D4dG(X;SI?mPjWuL~B#k_Xc(pG_ zSI!b5ZQO>>k&fGH$;ByDUV70gHLg7-5Ls&Q_^PrZz1k{LKrxbx_QbBcXbrwnU35cg z08HHEnAWLzOoSLqv!fK}bPrMa{-!$xD|U1b-`a{gnF9`81L_i|8B#IyQ>*1gA4zDE zeG+w=-uo84ce*gwKab73wa7v*yco>#bGC92Mj39GF?DMIe&uww({n5L!WfU6Ki#ah zkBN?~FP8n`943q!%|3`Rmh~;~D+Msv6L}!em0oX9S)-Ng17PI;>?gWgVhBmhenK}OOm6y#_x-1q zBc135f+s}L;1g#nFFIQ8)hta9xnkgcwLggxZC%gOD}Ygj7-iB+yF|K3)}h<(JT?19 zj5Z>6COhF*x7N5(HC!-rxD#Fsbp)P{ml=BQd+CQ}kjmx>xBja`$u*1A=V7O+wHC(d zj_WqdK7wAes=~{9hoA4PL1?2PAu40wu`SpX=gX?#^E40hjK zEx&oREsR+$IQ+fvd_$!{>NM$2oN5ziw@f*kMmfsXk#!4Tymq>oz^yX>e40kOuYPV? zLcF&K+dwdSug&y(@Qs-|MP)&@P|kpqHF=Uy1WK?lIWx%Q67pcm7yc*ph9-m3YaKRy zn(*^qZi1}M;ce^gAz|Oudrg=>9R5nLt;rA$E319*36=jFYI=UVL|;`k?hza74e7Bn zLy4+8$rs6xOd)+~_Rk+YK2OQrpqvT3mK1)2W&65(-;IeIwSRAB#EO5M)g&vezY1v- z;&F}34JkVgTh>6JZTIxpww{07DZkr2$Lp0Z@Ld0l@a0EO%r4Y52&I?(EQu=k)}L1j zzNooi=()$~cJG$8v|v(}fppI^{yI#f2hSnD+<0QmhnI{LhpP`o*`YUT&Yr5uE;yaH zmt@iFT`CSXc5`_&r2~k!Oa1YT9x2fb^M~-4AB48iJCL2IPl7J+Fb>}MJjTX7*x0N&9>uAYIV`l2-zn>?b{Tas_G<;1} zzvS_^-(LK+1e2UQMRPy9LB*&}7ULvS#3ryd!{-Ha__JK$BoRGre^)^TsuhO>8u(T@$ z?0OU6_UVn`pO)RbHY_Gg+i(4b4VJH}Q{r_GSe%q~f2EP%lF1^ht4uev-|f@>WR1)J zi)i|1>%Y-3o|WUG{8NZ|>}q9RVR&iAVe%iXsklWvxlqoX(-TuE}g& zfPYUYDsYC<^kZo@!Cq!Xou>8QRH|&x1O*6Egr-MHD!M?{7FdPw(a0suD^YFV6b}Ht zc$zBhZOK5Jt7NL3{afkGv63c9fu?M>?`&>!OVw#_csFwhieb^g;#d15OZ6qrJ5H#w zl6p4UQjV9LWC4RTsS>E|^6O4PNqQ#yamb$@*3;8I9Dh~)ZQ4>+V#D!K-$1ca9&|LZ zZk-zE9icX3!sfyxbZv0zbwC%e&iISwWpzy*>%>w2_Zu*`Kblyd@*JwY0HotV^CWZh z-2D^>9(#0Yo#KGuPbbh(7Q*NM=y@bTV)JehcA^)Pq=SkTtIjY z2$v1Z>8qF$R^oE1`q_zBlZ>SpyHY)$%v%7}-#a0K2N)GLyrMm0z>&p!`Deq}7}{Vn{&gkYVQ%N*sGt(YIQuY*p^u@1H$k~-7*e&EvE z4}uq?*t0Ea@@@^YTDL?a^=7Cnn3Id6Vo>wF7)* zo_3`l!WC3=%bIHaes>g?EYUmTjFQV%Bt$+l`b{b-na>#qoSvyX-&Aq;PvZq$@b%5B z*$9s=Hx|xm?~(yrQ$d*E-(&+vgPyd|!TFGu`{BZZ&-W3`LAH{=Eiyk9l6fJ5)@lbH znNdwPCP_W}y6F3AgRAO2FQM^e$sx4^z{f=N13*RyWB?|(+aUG;nii5WKzqFpP1Iu9 z49UhNzmJ4yo!@+tO|Ou9=tAQUM6)pxtvy9dv07t{vv{=WhRgxVAisc2$U$5=9Wux- zCNnbrjbuNSHUKIS1ut97|F#j1{k5tsft3%R-FjEAOayR$Ja+o6eDjabK8&X#THx>e zyRI_LMQjK~7n2;4KS0ac$Gqxd+H}gMF|Xm`y8xRoW6(v-PY4!@U?tNNs%;(OT~Z5;4y z>iW#+h1b%Hi-m4Tn zJ&l+X6MN1vp0Uz?+3 za$Y}ld;dtsFq=_Z%%;dZrtFG8MB1pT`c7KW-+kgA&p=SCxbehG2XdejI8SXXxA3FL z&BJ%S9wMUc@SXAP`VK7I(UJPXv^-Z}L-Co{RAT>@kO@m=b1;bm3!kMlaAf_FO#Y*h zEGzxXD=~f3Fe@fETJW>DD(7&CKQS3qu=97n^uK0jFv5beIZI@)^>n62}?{AXxjRl7WX;!fmu z4w9MhwIXwN-4Wl10KUcJzI$ zvcL@AX_RYN{HwtoW`Q;^+?yLh6nlr{D9g&+R3$;Sc1$YvFG=opLV?s5(tk{@9?8}>FIPr8ehJ*YTRr19v>N)Be_UNjR#ddcGrKSo8#iLY_49V0 z`*X`HO-zoq2^M>C1KV51n?l-yMLTtdBp>*GfNJUFqAA)(Y^~UeZQ<#mMJR* z;VQNO!{%|~d+mu;_YHaXc=GV$MY#M}FN=;Vurm*OUX~DaSTirWBM^ayX&CeIu zJnYSny>j35N22ERV%wsfO|~Eh)I2bWPg7G^3sw4CHhL?#BgVR%K_J!fk0&1pVo4a7 zZZzGMv*W`Xuxm+e2D$C9XkDqS3vZK)R&Rwlc>yG4If2%-^hY}VN|h8fH6|earhuce zhk(Bt`(v83f?s(P*=mHR%2KFY7caXP#YXj;oh?`c`J0wt9@e%FW&BCk`nxA!0&wCm zeVUb__0sw!li@AVS>rE>N7srRI+Ez6%C*OVAIHiJ;sw%8tEZ?2KliYl%Na*6W<>9d ze^yXqVNb1vKUB*ln?J#$Rw@I~F~OWHN*xYvHBPqBBJOf*S< zQIXx^@!W}bJx1RRWEXfUyN?p{O!8v^a)p0p9%2oQKfG#bHRTw3bC(pcyLR2gwc-lQ z{I8TjhEV{?7q#(^zT707VRJTx0$jvcMh60^5OcZV>!luZV|9AFsNI0a}8n_MFaDmh!b*{M?(g#Gi3Qc0ZahF_P`; z)uvf*VBUoORl6xe-jsy_H8OG2!sK?$(X>qBt{DA*)P4uSSkiu;dq&~B(=I;&TpYzC-5A)e`n%kY3y8%IZ zZu)g$5V_{`wTo##E&7P>SJ&pNF02E`BX;}7w67peCW`ciyw-xayJFSQOVcE_YoW5r zfTHcG{zxgWm)mcrU34&~Um|u|)8EDf8dfd6$JBq>9RMuBwWM2oi_dLOF00)AiXdYjP4Fkhx!Q+eRe!R(-7uN~R@u5G z3g)dHpB`E-M0t#BN#6{e%{Wv(*2>fh{rx3oqu<{#Y)8regLcj1w&Rdb0NTXlUou%# zG~N_`cP$H-Tg0xc?}X>&GyCU7j#v7%(aApGQ7AXu^(tmn==s8ivC}dcbkO(5>fB=? z+tIesaF}4(-O9e4?6vct2^)hvtIW{V{vaB4=*7UM_x}&iXR{vql|Fou~8<; zrLCVW7dr4ap~G`ZZjN(_p(6(Z4pPx0^V-D^&}XS7D=W#YPcDV;dQP|msW2-7USoJ!_$e()ttb6q))HFouV*udlma;E9} zF7D4aUxFk)UYfP;uWv9RwG~k&zhzPuW2)h&u?+t?Tj@PL1kmSpoR6F*G8UJTz_gVb zM*w;3#@F>V$&B<;hm$31zk_*PdiZ?&=LOm9^dMzHQ^`WR#DZ8Oe<-}G1@z1de;2jT zougzv(_m$Mi)+tnCjL%v`cFxA?maIo4v&T+taoA7o)|^a3tx*Z zbwDnBE+Bf-@mm$|UkBIFjboP|Q^P(@SmhN(Ud`C;Q{@b=lG{axw_P!r&FHT2$i{TT zksZ`0z#nQPVqH%3$=toeg#pubA={uR%n^^TzV_nX_see%p}gotFX|&1oN7G9Q8w%) zP)P(>>RB~Ny^5cxQq+I4YjONudOz?(lc%wlZ}rU3p-)1wNlI6Uw7xi>@7wx^(F!!w zeNDh}8YpKqcDI8u(L~T;YVFUw|6*+PLD2}mBXDBy&r)I8PDV+)wY)cRi4k_xnSB0a7mmqewO*!H7a)kj^*8IL?$^ zpCHw>j5q4Wpqic|*e=3+!(*!X_%YsFYLDBs`n_rVYGAuV$3Mqp>h21PC6VSUN&o}Ol1OYo!nJNivb!%@fG z@cMxY|K`EgFys3C^&N?+#)rctb{;$@)!c)DLt2WjJBHe8Foi`%m}hsI4!;6zSmoHe zwg-^}gwI@iJ5gNt92;mVSdRo(-3|H2jQ%zfdQ9Kl)dv?R*O&XZHGKKg`8BPGaF1ov zu!%zL{S)3vr-+Zf9poKoL<>h3R9*cja*YCkf$s&*H~*H@1$I)LzUb;rDP49_k35a8 zaKz7hasTuM#@e275ifK4F0|+=16n3|edQx* zcT@=XQz!%{lplI2_4>LBdNOjM27fZIjFI@-?r~`H4HiPC{#A~jdQuqNG+E^)tp%j` zP-i5F4ze+(>K&7^h&#(;eT}*v4t!6ea%!lBuW{!e%Y^LCYa`shmg-vjN%Qg70U7^3 zb4m)C0udKFY-&;YI6yl`UP#D~-@kxh`fOLyuiiq&juWv$!NP;7Kmi$d)Rj|jUJOByhT5JuBD;*UhI+qS!JQDCIEYhu+ zhzy^b3Swi$QUAUmt5>ANU_Ls1^BmIt%R#U@s9e+5@1wR)OKt>f-a7=SicK8b^@DyL zRZ=weCMfeC^G_%!F)^5=mXATrYWeyvQ}L)XUfN=DWtX6~7`Y2-6}x?^ek>YJp*0Q4*j2WfTiD?|k9mj3k2QYvCx3{%VB3j1~h-R_<{xV7Zyb=FrVbPr(8PA+z zx#nvFwc6aYWiCzgjM$fchmV$%-f(V3vu+1%FYmyVL!M1Xj?ekpY=ot%o(|?4WnErr zA;T76!`If}$9=2RZ}}#+`2o>K7mr8RjM%6%O|BXG9%xPQ+_cx<=5?x$ds$>S*KTxa z_&np?bh5(g5>ge_Cz`GqQBPhe)V+K~H9TxHg+-j_uG;cXkA=`$_k}>}-XUr8WB)x<+!=0PbK}LIW7oMO-P?ZYyNNvHfK&@uU6u5$f)^v8n%d#Mg_uQr@TN zXIgmLv*L(4%A+>SZu48jm$xP!g@Pv}gsLUx^u@xwne0fThv?I3{5ZkFY>RZ1?jc~~& zCi2FF#l-&pV>0!1760w~71g8Qn;qxA!?u^dt?UY|?O!^s8BrvJ)2{ARhbW#N{F<$} ztYHt^UA8+vKWrQ9H?yea>KM6uDE;xzFV$N$g;oQF5!EKk*h%qU^GcMBj`L)~)E{Qq ze1X>Ws735NiKTOXnb7aFTcNsogMA7O$8kJ5ZJ{~X}f^?G*i zRKGx~=agcXpG|&zgA5LG=#qW=v$k-fZyZMpb6(^9p{k{zwqwm)o@SYY4_JyyJbmA$ zSVK%SjNb)&30W>H)ZRuf9e<3j@N#9XQ;h(RyHO{Ys${GtlB+F;)Spm!jE-kaW1quM z=9#wYOJ`^rk>7#d!CjkxS(gg^n)OB5(vv5~uLTV9zgU>2vMb8;5M*mRk7M@$Ho=_z z3wZC?sg3@?X%p>OTVnKdGil>dwfV7kO>BNt&Ww#e@{1cIZ} z(7TK}S>Pm4aJ9j*wp{i;&S=d>)iKnasWL7T-NlrOUx_1Mq8m+Z%jriz=;-)!i~!^v0>T|%~m1fU`s*iqGQWrSUY{9gNulsSsl_j zt1T36?1}oWE!h6RkTJI9IJy4B`d!mr%B;nDl*6XKItP5XgYR>?8LmM^a?v?lqb_Jn z8FrZolVJ-IyEnB3^XY$wd0fg*ViGKMCEe(|Yo|H;(bGcl8vgwNQ$JmUEh0(V`e1*6 z06OiLjM}W4TkgQF9P8XvRI(GF#RV@lGjTMBX-SmKx3x7~y*}7b*^7TsA2)ZAK&wXouSA<4Jkg%2@jXeQm=0yNtGiLU(r~o!Y^rXzZ3U?qnym)!>WQ=W~R_ z07SZw%V%Zt6@_f^MfDe$lC{mm3(CCsNA4pRmo#T+iIX$poQ!w+7qQF;aPBAQr>Rag z&*~Ghay|3Hz2UC*o`Wek4y=B#pXU2?HA9c+8f_@#?LjR$&NVM8np67R(W{)|0kzlM zm{ufSB6MZ%{43x**f0Fqss$R~P36?M!s7&W(?NFt%C)70IIJVWmacql|2*cP_19&( zK(&~O91yv=erWj1sT30(!~VnXBjESq?evq^Bv4N_U{iLR9vZL*;XBNI1QB?Ghg*B` ziSWO5j9vTu!$1h>Of3B5X=*fO%{UhR1KnrhwRkwHT)_mGRBf|vY1;NQ!s>mZ@ah)1 zjOUbbgs0@6-kt5ct+qojoJ{SJZq-WH7(H^%zp0=azI+<6F}ndgxo&}FJBWQ4BfXWh zwmsi?I0`c&L`_*tsLp zJTpHNu@9P zVZkOzyt4PAzLMtW(*4tizc>DcY0jt0`JYa2C|9j5N4O|S*!_X>DmSSB)AFGsCvx}$Ln6#D1 zYxiWSuyyerukRFs#XtR{&TsuF*Ip>gZFwjV+c8%T)b+Mg`t{2r{-@jZxStN~Dto5I zS36ujDP!u^7QsBxG1Sz_@#gVI+S~Y8hxSls+~4WbH&&scn-XV?yZ2VEPc$nZ6WV!u z>sXIH9Hg&Z*X%f*+Xk3MvKAj09gHaHPvh=hzk3gP;)%R|!9c#)(cZesMAg(DF4gKh zsrld?$jNz2Z9_2HPfw_1_6J7IKg|2-o@4xFa~|#bFGqq|*YICT<_PK!Kk>l8?ehCm z>>C*BPbrCZ(U@Vow*Bfjnazza`7`x=US}LrXKHD9hip^2LiooubHEP;Z-^0hCx$>s z0zYne2-CcG7~v}FXqx4BmF?7Z3GddVsa0$panM~h(+`bNE#KZ9%A!CcNcB`|)O5)j zr1DfOs=%844=>nZN@T4dN593%Rw-=tU7)!f&TpoTQem~?k@i;2**sg}!9;AHjW{{K zvu$oZDAA_U-|>J@`lB4~(2=U-G3E=38IKz5J?-|2$8{-fidh=gl*@71)Cw*RNDe4U zf%j_mmWLPUqCsw_^irHiC*{GX+u|V^tRN$2QjfCpC-raQyVdjKH@DdhM$!nzK?Lrmv_SZpePmvjIG6WS@Ve~haRF{9I+(a$GFmZp zZbR>;I`1}MTKfiVNc}Ya&k)UZrNFJ>&`Z>EX}K)*`*2ye$nB=uxn819a7MbMBJ_Lv6_VQvUWT5gT%Wl*OQa-jJKoA)o)f!uO_54))CE@m?<7UTklkGoux zKmAj|TEL%a%s}V7vEv`3C|!GMv)>AA$JgQ|b*b88V!GHvL*e}@uGEfKEy-hN8WD6f zFtj;6eTrLmA`@o31Dl5KlZvzFp$`WvbiA^DNq+1rv_ieNjgiDCudIl>3Kp@NkS1af zOWM&S{~eNVf818=uOKxYc+uGB)$1Npe*1b@-@2@8l+aQpEVczL(~$e{5Ak%?$hF6d zwx0H}o|FY$u@v?!?X@35WdEbKOsGYEM3u#2+3Lemx#UyKXHqTFJEeMX|;60N1`+@;&`+ za>!jO%OMwJx7sQ36uutTTWT-n-yDD8SBM&Il|Mhxehg>>G&TNAiCE}%3x+_4w8ZzI zP^e0EZD-xrM|>42lybi3>SYzE$g!!G>eHX$HC@#&&pmrQXls6}S1I)Enp-G4`{U-L zgnPD8UA0Ty-O5mq*^Y@$m=SLI0Qo^JGPMK0e2xPYISi?8Yn>Sw2)-d4^82KGy$0km zZ8?ZVVzql}ulNYI$K8aF_LOPbo{+odyA)(pLq$!EuE%7_m8}iZ=4y?9u9FEYycA=7 z-_E=4(BJo)|I~qSi0V5}jYeR}BS~_ZTMJrqaFj^w_dk=g+n`eq+nrPIVX5(%Rwlh?KyVpcagS5 zr+3%SXYJoB+uESvWow9)@SO%)<;u?_*F`?cIRwA+Q@B}_&j{LsM@2>@L{h3Kzt)EA zvbPjUpYNI9j~Pe2<9+75dsMEHUm(&cC_&-Fmw)DK|q^IiJ zPHoY)ARy)wpdY1m4L*cF1lnMQ(hRs^ZR!o^Q2r*<=CD840Cykx&ks>OKyA3JLsvq9 zXbsbval=UT5G7)E&cpm3ck1K(stXIDpQ)bZ$rWpjaaG=+?*KRJ;KP-_K=hmj`TKF5 zxpcVxJ(^{ZoagZONZFMZI+P?m){JM9F(B>e7p9lys@g27Up`Rb8yQ>FaA;#|{F?xCwSCee>0w8=AjqV;v`3 zbJoGywG+r$oF`M|)L>7hr1;U>0Ez z5$YUiki>Axr&O&NUhrc#`Sqei9H&QW1_u{I>LNzG*M{TjZDf^=-b*)w(1=jGNL#aj z&``Gsv-cu5DjRQ0h|B2kKiCrV!It0;wuET5s0N|dLKenl)>gDMwl-F``4-kT1WJ6> zcDu^DIzl-64X*abTjAOh3?46AxGiPzTl?=Hj19b9kCzeaYRg%)$AAU}30bHYDHz$3 zxup2x(DRPR$Ej^uEat!T0W;Q=_+HptKc90ZUbf-!%~>jB@fD$kQrgXv8;cRSZDjRtx7UtLnSUU5UQ~dAE{m-8aUb3r z*y}7B9ql#`SvkeIZ}t+)aaMtrLwCMUt3lwg>x}dI*Rt&CP$I z`wtcli|UysX&Ag>0+@da7EUcZ@GY^$1YLKt?7;Ll6 zpfh2~X?{$x#O&jq$uTa6IR^It5ugT#SD*cIBFv&IRc?RJt;!{OkCFqZyRoiH1NmoB z>ZShG2Qv3uYrXrXs@SL-xkZWjDU12l_>X3mpQwx5yr$QzowE-tXE77uzAQ>t-`JqR zdi}&n_fHOv&y;QRHa^#B5T!<-!8$x>;Iq^@>k@b0I{NookL&~%Q}wNs8gyGrSw)+s zx^zsJ`x~@{#_!Be+qXp;zPJa{#H#Z48kXz}mMlpo*&iHin!L^8%&HB2+8ufz!>lJ8 zjA1yX!C->HJmYZR`5CjH+6_J$nmecm1`w5Dsz!q_C~9xg&!*x&GhDyfa(m!+$9f>l z!@HRIFxn~&+SeP$t-jsRmA2v|qZgKo7R>H}7Voqv4hNJ0Uh=`EslmwfROF4BQFY17 z&u3>D?EmvgPmCHH>ojGzUAcbJi@z(<=NBy;IpW1%4Ly+2UKQtSmiPoqY<+fIlK^o_Yw#$90 zkxk&frz{;CH?Tp!=D1TA9GD*Nx+!b^lRcxBEwUKP5~a`s0~=KM!fn?o+($HfoMz3t zoMP0Nv31B0k2j&|5j_!Wkl0F&^(zY-le*&Ro0wPqZSMC-qDn<*P{$u^;IAq!OIS5I zQF!vQaTiOSmQ6iS3)r)&$CJtl`e9A;lQ{>{rvG}w`!PSfxknnho)j$_tAFkGX;*Fj z9+0$c_{yBiz01z_Oy0k?2{~wVy)iLjXkVYm#Er)|TYie{T+vOdf#-goG0_`(Fni?~ zGv4E^9`{vv?}>GaCE3Pp@Tj<%m^7p4e#HF70}h%btjU0xu)V9WxFEZDdM2+#@>lLm^O>2c^Z52bRS~N(P&vgA}=dOy( zPft!;eEj6`1uD`s@cw1=mVILjgqAGbH!NM4MB9~Tb~SVCsq=$RJ(w^}MVCph<7Z-i zr4qYu)u3edN1iE*v`g4$@Oi7;`TlbiWln8VH})A8d+vZKoK4>@PuyDRopR++8ApZP zuc5xI0R*eeRJ;GLK|Mv*XPw|iOrQCyB-VFtFZz_FhG@N61M`oiwxhP^UP|e5GMjK_ zSW2`SCK$icsx+lrwkp*#-C)gmn`@3z`=$|XAE+4G-nev`Ig^gvU;9hGbl#%h|y?YDLB05X_MRyL5; zLBCAzGqri;g9W`df5zfwRkg8*4_Ky7g*&vy6dmt#aPdOnHrd*LsUfDqDUQWH&tl)> zyg#;1~&XD{9P-GaT5>D#$^YP31vcQvs0KdpPj-}pZX3iz!+ zJM5&&3AxBp^gs6^WjnvA&&oe)OIJGa7OGP;Rt&A`?&1XtOaaIMVArzEqA{eG6eORVfLp{^D}Lk-d+Ek!@;JYSx) zxOC67KmT2GQj=6&*2^r-H*x3B?R>o_b(QGhj6*w|jFmL)^%&l_YM9&x&h6(1*4#*$ z+;;ougqJgQG_ea{NR8cl+EzTid`5^cSoZp*mOOhx#HQUw%hG~bDth-v6_u+AWqV@Y z(#ykcq;1?2pSSqre}=x7iqpVna=#z*>ks{s_U7DO(k1;aSp&bP?eB`x9J&%pxCf`C z>{@eo>eVkN*1t#kzU}>oC4Ks8>h4_aml-?!ej4(l;rixoQkr-G^jtdA8dSUbpPfJb z(4&N{8;HY&yOFipDZY*tVhsnLN4qG<4Vaz8RBtcGleK|McPi zVp34s3U|K~G(>T~!avvM7?!eU<4&uCp%!HtTolMx5qUWwTeIT=&X$Q2XFW*Ns(n== z)Iff3R<9`?Pahro+^_DXY-zk1_PRQ;P=hX&{>Vv_Xv)Bpm-?13;%Bvr4<7D)aH<9o z&Am4^vBT3OuBbEHw))z$_{oiXoI=By=l_G4g}?7Que1E}zwi6S`Lhk_pTft1X*#_$ zl&!u#)v0c~dER{T)*^L_^P9EDZ=DO*pvnUp%_#B_OL{8iH2+D{ii~9we@u4jHOlTE zN!c5fs!YWVmdodvclPudIwfmn!k6dcMie{zBNx2!s6n4N=mN*!ujD?{Mt!+s^4c#4 z{S*EBEAu;+%cm1If1i2dN$T|4;HI(X7XLGsqWU@w@}!RT*LTcfk`Ir*D%kd{v06c{ z+8z?>%4+MCecoh=Tz+}9adm)W{Pt~I*X8#+Z2cZli?pe&v8JW0X^7M}uCAsLphGmd zki795wp1i|B&@X#{^_T-Sf_vB0+rS#mi!h={zJjR3zMe4%3K_kZC1@oiuyWSN?KijWW^p9MM zg8jo2@D5@%BxBpUd413FDsve1?MkgrGiDyX`Nwac4D;9I1wz2D^_t3*^Y|l6w{v;b z`o_8L@sloX>@<&zsMe&TFYIrGG)TXCKJLw+%MaofmQFhRb%*E;OUkZax@X~@sQ|ed zM}4xqE`9#3z#BD1oBY+O;qC|ghO$K!`)U%mFT65m=(q>T6LU*en+!iaT}eCy;&3%d z?r`z6XjX+CVx4`qPKkLd+6DaoT{Uz1`SH%URPfyOnsX%XVux~zm+^(_a0?F zeA!n@_cKdWaOZ&4B(DSMaVH)NquC)QWVf1 z+qXB>RcZ8avj5NvQ)W$1TQuj9(dxJ{Y&M|>%l&@GkiDVa330n>ZcZDwy7w+6Vr@fZ zV@InhD^8Ici~LS+_D)M*+FWUJ&-Cp%7Fp#;AG6!{!Y;jkiL6Re_C{trs(jowU4^KA zf_uWUZCy}nv}i|Y!h&Iw$m`7)ZmF=@NQ#Cwno4Z@dQ-_Kvy8G9X$3Tox^>xAjY@O7 zQ}1k(q5g|(^VgX($}X*S-v0ck8d*^y`(2DB`GqA}_IIBWuWPSUSMg@)d5nB?Ta5(% zXNfcqY5A9rrhe>`ojx;V^U`x?7YDyfq?E9#MT2ZhLHkho>ya(Gvv?~EHPKaL(jXlFSz&r^*Tz_xHs5~N-ExM*a4I;1IRiNH zoH$MlCz|8HvFF%vY&kX@OOAyhfpwXp%O}=6fezttrSvZ_=JZB*SSY}a)!{LYv`Dg3 z6i#MPWFnR+Vi|LZ3N_J*7MTi)0tZFmLW?r7qHv`}y|be5phb(jqVV?PK)x}E;gc|) zKo7=8>;y!c7;%MM#XmqgMvrKXisBIgspk=nFpjU#kQQhE`T#&-Qa~IFV$VlxD_$9o z*l-D-m~aV?=tvuQ1cydMBoBy1R64sjhCM5(f8DTtALPq^DbZz{(z5OUIW{!V*rxQ< zoVuZ=Uor35E!x1iIQxI)93Y$nHk<>loCArR1Noc-gEdEP>0q+&>xs%aa&q(gy|h5z&8l z%wFD~fm!7VxTH4^#?Rne5MPQ^X7UC~?JSov9s)?V$j5@rfUZS!S*x<-jWGbL3PQuE z5)wT@nSyX0AcFMre>29YS9>bzY7jLJ`bOKdMKySFi5}tb=yarn>55>+aIWYS=>e?Y zAc+OE``Kt*`B1kl&G1_D2xi7Plt=keGdR?!umlGJJ6*Mb1@YvK5|VtLz>r9IQWyig zL65X|Av3_R-Q>c9bnoLW!I%vgHk0 z`pE7wew6N4=uj7&5_nIk?g!uCAuU5sD%S>j3i0Dfh5z`*{6BA6M5tJO@vsQcJGf+r z;3{!9p#FvWExN&YLR)N+(my1l8?a;jgFZ|zRE^kOA2CzP0W+B=Fj9CDOT={S#Tmpj?hN^8=9=05*H-egp?BC!zJa_^tV$PEqiO@xC zrq)VVB@5Y0*OD3prbZLz)O$FW--Fx&NaQ<^`|m-X(S@cCd85{sD}#HCNU?+rNa*{f ztHN?pVnzHDR*(`axMwUXgFHoZEb_jZ8jzQ0N>065)H{$yO$h9pntZz6gUr;_l6)yE zwF!3+;Sb zcoxxp*Qhodk&ld`*c7dSw)2{35zs~*rF9JS6-|f0RfehbV5hGNKR+W$FA=wIBH+gG z1bvho4KwU$$9)5_XzxckMh}E_J(x%A5X-{=yb0_D;C+H%q^Ouu9b&-i&>`GWZbJI+ z)Pf}o()Dn?w^3D5cMmiLjp4y}H|SGq zWE93L1Nm@5D5g4>EmLeovh`5*<59P6Alnk8Xxz=1;XndmyI{~uGF)Jn3f_jQLj5Cx zIqN7{g}@_)4=yttl%*V>aZ&3COdXB$_43MiL69kZ?h>VyA{iiR?>8Ot80apf??!fI|X! zQWK=tCwibJw08xxRpO_IR6hnlnAIamo z6MxD9dw#dBzo4D*&(BVL@zp0tO*s z0S#@zNpR~;^$0F<>wdu&Aig{l_|U_HCm$@@nA=OmLd@%6h$nW<9cfFc^o0Y_Xn6AM zL@!H1Jmdvn@cP`3D2)g46p$ExhdoFN`sPXpP#QgvU6vID72s~!V@fRS!{|aS6=xNF zb+Hrq9p(tuh9OA}6mQ%{h0G$$fm~Fbn>C!{U)QyEgp1MI4fD`fXR07yIF7qd5RO*dNzK{&cv1C9m<9VxVck< z(NnAox+wSrI*nnV(BdUhZ{V1L7{NN74_7lE*%(UM@q#Igz8niHPz&Cw=oAm+d(>VJldX)(fA4?7sGaF9muZZ7MB1DqF6 z01F7row|WJ$^ke)*VN+a*<&$Kfz-0)K!8EuI;Gq)8IQVrec3LB%I>1Bg8Yh_spddD%C9it?zGN^G_SuYqq}oGdSwNJ|pQ%@UdTcrc6ZEl6V>xyJgVAxqucfgK6RV zk)o|l0R-*RGulKbp(>lr#>Y!&=_Xsl!nd(_``P*zj1C-HV<1izKwWkWQU&zo1cX`i zWxMRT;^m0!EsG-;DqdF6a~*vVD_*{kdnsOy%0rZpIK|5vd4}?(Q1NnHUaojKD6dyi z4QKSk@Mfw7XcHMdM|fu(W#i@lV)UF8?@Q#LGX~D^&WEV{A)}{b3bXFQ)?X{?9_r0D^f<7Bxsav6`~rvHj5-+5xq<3}*SX0@QEvBBlzV~|h7QQmVlbwgp{X!Y3H5`yG@bVVAvQ=n{F=U)!dgac6Qy^AL{ zhe}>1L@#b#0$uRCrpgR}H9qKR-xVMFSQX-%AwF#J5eC+YRoIfb0#kJNG{&KBrpq1F z>c|)95=}Q_DMc-tcf~Whm{=46FJMEtnn4v*Q)}Y^d4;Zg2KwPcBEdp^o1p1|u4<~b z$gX;-CYP?(L@d3#+P&#tgHF`dBj#|*gTWCtpQnC7(OPp=sJ3*o?f@t25I)Y)m0_l2 z>S75@t$1`WG~N*xG6Ou}lu`{#8oUte&&yAvSbm2U5eWeyNC3{k z0#PkcvCd#e5H(8a-@D=twACTz-UIc}pSVDdMJSumy&+%#*C7CxY|BPUz;B?~ix3-F zZhSnK8Kb%Ji37e-hb-btgT3)EyNLlkqnp#=0v*G5p-kykk<9CGAwD1l>};&F7v^>N zAk|?Q8QoWX_)>O^v`WXQ%~cJL6U&3G%31)*p&j_~rA8E$4yx7^+^Y)&VUExx(0L2k z&UJ|m-KSKW4BCf3_yB!UfDxS?_DlKr@})GYm%a4`42TsBh-^AfU`L!$7KZB$1Jb4g zg49=sK5X95GmO%lQ^XTk5{W+WkAgvRVz~tP8p2R|^TD}>0t}X`)RpwdKuebkT+H}V z0R|zu_<+L{4kiHu20bn&n2gXumkIM>s7&>Ioq1zSNC0l?TGD)oa7k|=;pi8e(lKjXgzf3#H~nYn;8&H> z*4kDd_UQ5%$(;rn4b{qqk<%~*);ta05o4teO+v^$6#MrC@QWEB2Hny9VaY?l&Bv`- zfB`9P2N4h=(4>(FQ=^bIgvmu~um{IQcYTWU8AH><(E(s9vg3>vdOtp0DzK)(*a~rJ zy1*`v(Z7go;6vUPtW}6cWrh+|NKmHh44iquOkwSK>vczK_IQYL$4Vf|q9+7iVq8M5 zd~nUaFa|(HJ2V3Ggfo>jqU!Si#?7`@`V;+-5*WYsXgP=J6Nmw$9>@(w3TDdn;2{GY zG8D-=_|$_T#FWR?f`h{teN+pD7z>aau&y!IC063nupngR1gzA!fX7E?W&*}f7Y$1& zpoEP`Xjv+v$@d_|F|afkE8$>HuwbaS(>HQMQeM$M6j1NKwPCH7Ryiq>$R)Pi`RPovc^thy_!nyn#Nb$z!r1BVljryU9l zMwnkWN+4F9lvR4Lrx}(oLP{Y4<3y^!A>uGil;A;~W&o~4a5M`x3MZtt(-y!XY-*@A z0?vq?PK*FJDmSPKzSN0SBb^uODiKjFP`wopt)pD}s6<#j_;93K2H=5GK&NzB`FA%2 z!xBa7?InN;tY&JhsgZwM*ZSf-5=#YdY0D5+9Ai&cr38a2nn^-405R z*P)P!+7l~DE4m&-Dv5Ckl|?=~^VZnzPvSoKyGagqT*QpIw za(LX{@EBuDHH5Ax9trY!QV(L+tqlhl04qaM5Tn#aY?4BTiLtOUI?sT`&@Y3))d&|V zgA+sTorVdvI1aEV9$K0O8Gzk5K@T_^EQ$>*WM~+phY=nyiY89BhB|}~-SXo3;HsQN z0;(cIA?R7l%!!`yzyyYs(J+%9O1ca|8P3>+6F7NYDUcfC{r1e5iu@y&#MQZwzDi$5tBQdEwWObe_PKh(WRF zzeSW4?lfA&8~Q*L1Jb|~*b+B>vk>RS5#u9sXv0c^fb>a#P=`o9{lGM-+-T11 zAdPYD3}5QA-85&guZM{%f~HGKwS?$_}E|$c}8R|P*VzZqWUBh`a9tJt`Gb^G9Gb?g+M|0{W3S zz9GAL6!D1a%}(()luyKpw*Z_ZU+S}2XG=F)Y6o4s$O<#S`%j>7NR876`!RP%bYa^bGb44;-2gzDannDSX6*H(jbVtk!f_gHd#I zoTX--z!7pBQavgXbXE(UkbusIOa?3it4{m?m5vV98%N;^0?{gTG7_s}*eb{)n<12% zqUt#$A3;|5mda)}0fQUSWyScDbb$gQJDLrtx-MsiHK8D$)DW}|+U$>=_+obw+$(x< zL3y(20tmf=MTE|b7M%dF9bg4}xdCcd3s<`#aYa}L#zX$t;DHQnz+@;_v{QKF!m z=EEHy2IynL=s^XiEDcZP?R?^-ps40IyOVMVP0>DS&Vxf6a0nxEa0HDof@~Z?VD|`$ z5y1^d;0+^yp}}rPVG>LmyPFM4d3w=odtp(DWNl*yA4iOwoFGqyXnqg=VZ3_#< zA}op?#be`W5t&R2QJE)2Dfgj8g^x89`Be}l7_nJ$_MuFIH89qB(0Mxy!X9h@g>)l6 zFi=ckCFO%a^cqYM(dUC#(8mRA01r?tLHj2-&)~ew5k{A{8C~P>02oyhG3tjY_@!`A zp{ej1KD}&^>Y-~!`d}2CijRKy=!=g$8X1G#AdKd$qZuQb=}?732lBBYIE{{(m*YZ* zp5uuJYU=`s`+B2Mm@9X75L-Z_RDT{9D`V)bs-OZuZepmDVl$@%_B7mDB6w1k2q0nI zM6k+y3PD-2xnKb%LII4EN@z{Mn0YiTBmm@ri>ucH4Y!-2kp8;#v<>G!HNA_%Oz3R) zRuu8H;G_U5Y@6w{=9Hr-`kGk7u#5}9)?sa0qt)soFM7>{Vw5qos8$q1Y2g~e=(Cv> z_Mfn@QO1`QuOPStg{tDpM5;~p>P;#w+;SAPVp{lBF%Csw1r4y*(+Dt}y&yv4OFk}S z+CGZ5gKv$dF$g?p3_r_AZv<Vu9Hgj3rI&;)%$TnqV(|zO+|=?C1@U`XcWjq>``+U3U8w zvocXsxvmm55fqQ8aKwj4PpGC!)PVoV)d5gxToZw9p)^Lohdn-ADJpw$jD92Wr@=fv zBJmLilq!Vae?TZfglJ`FboMAhJR1tpb>#0$3rPSvjhY~(-FnlxX4Oh>5>OkWcZ{f$ zilZL~?a~=N9EJ&oe-uy*0J_4JfGSOlW&lL014gT17$E>GMia6aAc;yy3PRR0B6`kI zL3Yzn7KRFtpaF!0$_{}Wi>FG)t)>^YQ6K#0Rn)aq%ra-ba1`pbLjM$8A8=S<)S$8<`iyg3uZ<0K#aoO z1i3OUgW%|y2ykaqqYv7UQ}<;t$fHt|GJDtk_{P`b-->Zk+7CR2jMTUYiznPedDyFI z9!O)%S}y`3N+TL@F=0+Ac;69P5`3g#*x+UQ*DF^$ZptC1#sgoLgW1}ovBW?lLt1_@8EL+tyYpaJGw*gzA?jVd51}{y*v|R? z+&Rp0nGFUV@-)yvZ`47pKx%?Upog+(Lt2i&Qvgq!N))mHOxg!nt36;sk%zy$Ldjzg z=3uN@9)4AL1-AhP=L>V%!$YWgaE2>*<$#~GASLMT+Rz$UUToV;X!F5-TGZPl)nG;N z;{t8;%DUaZMhL)=QEL>OJcW1`aTJy5P>n)1LfWeaul?+T6Lb(l{P3J%k9&{=yRt;a z^zK?PUn-kD1e~4x1S85Ve{ z9vKZs5sn+4a>a;mMRQ(=YT5`hZf~vFKeZr^m4Mojyi6CO-ws1Xf`vQMMUP;&`u(!t zh3OQq;=@{$3NS$eXC=Pk$38wnK%^2R!vRyV*af;Q1dYU13QpWkpXkz$Y(Nv==?@bH zZHh_+RKR7&)xxQ#GZl^wrr41IU&?kFAOMZU@?n}daEby`G}nUc%t#Rd`K<-bRDB#0 zERd#uglPpd0(U<2W+{YAKy_T=O*r~6kD=WEl6D>7QCvs(={Vh;q}!8Dz4wNY5D0bD zC5ot~_hK7NY={H436ULzz0*k)gXx$mKoC2m_iCH;#Hmi=IK3A;af;L96esh~dwaWA zByjS5u&>m+z%xIIPs#FlocR+x_j3om>AvIU5t25(m~1Am5^Wy zJ{)N#k)L&Y+Hs}-U782>p+xxS?jW*C^nXI5H^mtl#!`+YYo_hPy1^G#oTQC}*Ji>H zw=I^t7Cz*#bWJ6tT=jaL(W@!*evZ@ezo;Rt@W0GLN9~YZOOmqgG-7z$=_VLT*JkVx zqG+f<<9$>E5qO)r&q4O-E=UBEfud!|6>KK}$7B!O_F5q_8gK?sq^4uHqJSn%(xBzU z#OTjqCtWZhq71W|%JonVz*NOnD#E&xVO$}W8^4dPjD`2oLaQ}e0~p=GrigeNq5%>4 z{d*mxiJ1&z!+$^}`Gi@2iaJY-_8hW%tJEK@8FPj$##45K%HvXw!|(1PhzO%bUs zxD*_yxgUbUqUmun5)f0Uu@%ZAl5mE}K%jU+UJzpjB4L5e11#lgVg_-nT}1CoXm;)% zkM48v1{?v>=At4vJD}GI)x6iSi|s~Os%E?9jj~iCVstV^eQ>EZT8ipK(|xp*K5SVl zQLdF@!{vpwI-;%Ryq_*AGGMHKfYu~sBUR*poGXY{k*jyOKtrgZ0>iFn~SGW|M%wJ zK%4WWTOj9Br-b4x$GDptfG9haxzq;r`QHj(Gp8GU?VPSu(&}x#Ih-!_E#P#CZ;2|e zRQ=Ye`pvAEB!fSd(^etxam8FqMcRWxJlLj{i>XRQkzu4J8&W)|@gc%x7|;=s0Ow>H zYe{mLh{5Y<7@k6xG}W{dSV01;tZu-K1&jV{X~|32R*EF)?uMzb*xYa2k4-Sb7qbPx zdILC#5@}o#UpgY6LTji7Sg)>{3W`?I*kA!zbL2GM|MmJ+?R9TNl;&GBhnQs-X(Gwt zQruE=fyujeK`;}hRcksNdqsGq43?e-Xu9lF;iAPuMox|&aKz|mptH{ea{|S~>$GhU z>-}h)_39CAUTqg@(QUABW?B6%x4cdz!L8PptR;axK!Si(2LxVA99V@-I1Lt5;VY&) zcNNx9A4#Tl#&O_ae&kob)*mTGFm}^9IPosm0-HBHqVP~yIumeY_ z3qD%$n5JTe^&5MMIc}$SinlkrRcsj;)rviat5A zPoe6wg!-8C#0C4fg7Xw&o)mkJCIld|hTP-mlO_99bDwngEEn;Q1)2&naEf-dABUL9 z9S0h@V~l5p{;00w3yKSxO`^tpP(ZwGn)xyfGR9B6M?9^+0DWfD+|U)wV!9|qaXE@9 zwpMp=i}fk&W3XlgI`yrMVV`E37~5GLxFdVD0z}l#A3tutRQCztSl`LODigJE5$;JPK&&)B zr^%VD`{|6fX$T$JV)mRtL7Uc|9#_dqeTbHQz`*5tXt3?d_n#tJiNh|Zm@F!sL|c2j zsE!qtmQNIdGrBW#Y}jS39uUH<9}nMw^$UsMpageGJyFyQ{TkiQUIn&E*bsyxTxgU7 z|Kp$*)k z%~Nn2_@+|Z9QF024Qy``-$pVrLO%*rNh8${C!Xw^r2!;6OjwrK_oP`*(;c5vDA04Y z#6Ihc1*{WD8c6bOH$aw#g(^6Lks%NVmYTzp?A6o>G(x*C;E-+QU0I|dj#Sxl%U4Jz z!Uj&-w{qgGYvTJ3u?jc?w(eo*T&gJM<5RWVZ3SvA6-Apg7kdZ|#{I?}bT60EK5hCz z;xDjdJ)~s`{kX$b4c8G%r_=2=jbeQFrps`+W{`cZx|HkU#SDznPnyGQ)?x9+uq0!5 z#-*LwuDL@Di!=HOO^cLau>hCIGQ*g-5^I(MGc!dZ?Wbm; zLx0g)__KA)zbyry!?HJDvRRnr%hgg$+hv*A(&C$H9n)-f>-P0(spbTWwREG$&T7v3lGy2t$^#-zm^`XwZ_Vt>}$Tz-8=CcGY+!5l@ z4Y;llY8kKWAOd>EY1vH{M$JMe87e&}%+vP?u}lA;RwBcBRsan-@@1-ndQM>p&qbTa zL6Fo;@B_5D1gF)>)Ti1eUn$l#iOpWDX?%72T7*C^% zWCQ&fhpSX{xCS}yU4J-fcb@PJ)fJLMf z;_hXxoWqd%i$?Z7<=u7j!yNj`ctdM3)b9=-8vOyyhF+}HpGm0P1dJ+j3()_A0#gAZy?CFI9%Ddyu2LxmnsaCmIv_y`C!F%xvwUU3f@gtfVxydq1(|~ ztTv3v7yH-I2GmM5{yWW+uJmu0h5Q5<*6yc0;OkxWO+Y#f)aiVWabF+xB^iVVl<q$Pgt!Sneimmzr(0y#3j{}@Df$Gut3W_yxHEF!^f&?(t*3({4(^ob_x#|Yc_ z!>d>_TrDNUaZeJgTH*v8`e>em^r;of-`H(q>4B$8(;s&_)z{XNYkxH^*ysUw<$L{y zW@WDa3ui5VrTU^1pRC($bO#NR1dm*veURjKaJVenEad8K^lxDm4DkBPPMiGBG+)$t zXe)~~kt?Qph*>U!`^iqSu$`Bv^Tj&lCF!Qk#pDiRy-Z)BQzM$OyQEx|ZXZ;|EEIF> zgK#3)VFMrF^?cKf_1bOrB-y_eIqq7a)~jN9vzuPUX|od!qE{xS$we*|xfS-o47@$I zl;c~1EtL;W*(^ZKM6HW`_marqVCkE{AamIc2wbn-9WP??2XXMLtF>6xw329Vt=$CI z$sDOHKSAzVNEI{4z(o>U%6iQKj!+t-|IzMRFEW8r9x9`4r)pzI7K{8)YP~Etf{)4* z(i^-iGaaN^;iItIWy@CGADc|?OBkhJaU_)sAF(VC?=Nvd3zAh!G)B`^S|ugfdkCNO z$4UjBx%AA-ME2@kz_1&dM6nq_u`PsQslc#eAQwNfaV*Pi2<1gF(~5dnBkevXB?#D( zlAF)Ou_XPdCeu-sKB2JlDYH|${v}jG*@^>QD$@9YCevS0BSyZc8W}Kubl%RW`}auH z&5)=&jeu)gg4{ghnp7?iIY#UziP$@B^p;-A0l+!7nI722f$aUa=???@5(xV^Rxn3Y zd*~Kefrs#z6hNaEyXYjFJ;deuJ)#$kEsuilGN|RoKsZU{Dv~Gx{?!ex2LydRPAd&G z+6TR&Q32aZD~$16EJ3lJ`e8X$R}euz3z>d48gIZ<(@gNe8>U!jiU;)}*N9f0vMYkb zRxyd~Q6z>oO(bKbJnSQn_6s(z$gT(@bFi)XHhY4oL6;mn`Z0NWBt4!0JeCh`13ku) zG*9&SIi^P{We4f8%^|$uxjcu_n&S{^Jz8GXwFdjmV_NRqO?Ul*!Ay|R+}P|G{rzte zUV7%@`QA4P#ya0W+n6!?g=EZrhgJ+a@|P1KmFDBam^LP+E_x>3m@X-(9u(wHDFF%f zt3aS?JgV@Ribrt-31R+Be-U$U&0iyl$X{#HM~1(RD`)#V%*rhPe5%Bb7REWvY1VS( z9RGUNlY89Fl{xe0B#}XM zc`4U@GeYx!L=u|+<3OyA!JQy9|1UxatpF%&(o=pYc@+j*OI2r=rPz2g;#&pc8**BS zj~8S@lWTcwcDr0=mTFaX%{L>%q0&e)EJLmwxl;76LarQjmE4NDY9`kS$Z)6|&{{OO zL6PBfv3Te{buC)Ru+$NmD~pnA3nRW+Aimjy9-91K-`|+}^gm0I8+vIblibi>B*_i^ zlVzdoKsu3JHb~CXWRZmet|E}xLN`6as3{}hmDCi-lhhO_P~^asHLB7=V)=naDGLSK zCc^j(iSg5bze`v)3Cy#iFXdLKT#ju;7(ND8N_-4#FlC{%z^)K{OuLyZ6!3?jQ`!Ww zP~dnZhNxWlp$EnyWTC)~utN`*h44<>hkg@Ff~~VL%h_d5N@BrQ3L!f?kgVS=g^-6B z;$B^kwaBvjDK`yGi}WXyEc?l*vaBa4%X)&c z>=gYlgxP1DHuVvuC`XXuIu`^TFCF0RVF##xUml?TGxGqG^}jipjMPurB+@ZVEX=x$ z_1bW3=s&J7n`sv z)HKn6MsjH5rHG_wV1^P0O{l@HRf?(kYknJQ_Ntmr`#`6D1n$YtX%zQ~o~fuWRfe-T z(dU5T9Sp~0M_39OuO}7br(x;nS+}IH$7u<`pMPqT3#Qdp_g_D z^AE82fgQkgN25~WT7tOVHWSI3Zi(x2G(f|%K%#mQPTkdz-fLA6WVqD#z!ovU#-Hn43Ir>qjiD~H=tDlvFO{_|1guSY;DinkC zcVM#g!BoK*v{?Tnp-<^UyIqD}vAsFg3$lGgz5i@eiT!7%^s_5jiLABQ(n?=3G4AAL zl4oOWhc9I^;w{^~Cb={A<~W(M)$jEd`)ZwK9O}^!37JC4jC(-BojG_kXh~(cKBlr-k->G&j*xk)pj= zqP=ql?KQ*6Ub=gCJYd_Q9~GjbLn{Y!;4hM6#rk+rOq1f<6_>1Y;NDM=;(rQq?5Mhv zgz1pabH|L&D1vUkoY!bbR`29w`GD4a%U<*pqznIL!r z>PIXTT&v1_iSn@D=E;rUAg#cCn#Z&pFEH(sdvu6RvzH27ydCP|ogHLG&Amu&Z9Gr> z(_P4X$LGXNOO*wp9z?k?{2o1|_!nz@se^^=`MhcfLU|Dvr=0fP#VKWY8`1@rS-`xDF112izc&QTnFCJAHr4Mt>xU(`BXER67db$;572GTVK7`CpWEqg zQ-FQ1$?a{4hKmRz`GQ%Nf;eFV8~*MO-F z_~tp)@4l_jyu9A3ICi22#m7G17S(bWwUmdn+|Mm-zTHF))|OtMUyTWb&GuT~G1YQ{ zB-HspS=Dl{@3Lwcqn3V4i`Vx-ZYl6RLGaZqv*r6f<-C(`!>6O-hezVa-M02j7_XnT z5l-Bw0oE*_c3XpLpJ8i9-D{w%XCb$lXxCQc3DWLr{VXoQ?-N?EL9070(p=V4P$D zg;9!=gT>s?)*`btx*ooiqsCi|7wZN4z;I~Vu`<_n( zTe8uiY$-Gj6-qWbR31qt#gdKA2BObo_BS+x&>=rM8y)J9xH>e;WTW*%OQW*Uq4hLR zV{|q;v~7GgI&@zI8y$MsV56;8Hmc#y_rCyB$$OVF#4GC<)b*Vb@co)a60rJ~j!3aw zKPf?suUk32WYxkSpA0R$J&G2dqrY2e;ZG?o{Nq+F{28T%f8DGs*1w~)@E^SZctD50 zS}pvyx2}c1tT>6VXyLxpSE+@U-MSXu;EcOfEqqp_7JkP~v~W7YNwcT3m{#3ksK^T( zF0NQ)RP?HfjaIcE(3p_`M4nILk4RDDD7~ZdHGX zL4T`OmH;=*y9^z?4aAyiH-1MiBqp{7N@1Y6$Fxvkai!A6`Qif?Kj$8 z$;4r2XE}WfTuBRr@0%hfSxRH~v?5vkIw_6q)=GH6ld*7c71LX-$_=``v>W$J&Qi@))Zebj^rOnt^?6MWdR95Np0hf) zex{sSzc4HF^xrsFG4=d$A{%6}v_Z~BZl=nWBF7f?Ch6YV3C-VY+S+GJSC&1*SeXx3 z7W2RY#R!!btJl^)kpnAL5nv9my=rhFJFpr}JEn3>fxwj)i>9{P)qCxO;~LF-nLHPn zR!+kw#Z0!@;IwQ*$3)Q#exJX}`m2 zAr1F6wTAntqI;*5S$q!e);?NKh}Yc3to}jajhUS*+;B`O>G=mUk*@arR7uY-Xcg?< zX(mk1%V!+FgP!@B^e9Hz^VA0M!ETG=GT&)BV$wf2mGY^6*aOsWv73MS()O8@PN5*x6XO5 znscYsp|w|X5dXv6*yTU0rr|BgyRXlG!K}>pUv=(fFW2>`^yXoDBivtt+yYQkgQBPm zTfd^lJf=o)&k}j7%|*W!)vr|cn+H+5NvX*dwr=EZ16@vkP`?Op+#qznjge94V;N$t z?ZzgTAdT~b86wGcV?Kzn7~#E}6y;{xRw&nVDqPP+qRLCTRp?ihOlz(3mnl4R=AJs8_GxaU7+{ML2O6dHk4r8rmTyv4fT5^1&i5HTo#$ZVlE?Cuyejq4D)j% zXVv`kf)f-)Fo)eNa%2~Z^rcHsD?ulS0yIGjq zWU!N!Xk&J=895e{(+#d+G8;<-N;X>agSm9W2M6}23>78lTpa0*8^*cZHTaNXJF7`d z{G=iEF9qA-+-8dd+$v>+i~a>sT21zpAFL~8rc?u_w2|lla{G7KSLbV$yeROxR^~;4 z2P7{FJgDWdukH+P-FFt77p_-wpelCR?KAG%@|#_?ffLGucS$+xt|-Fg)!r?y*uYbo z?ED3J#Rk4)VG@DwP$fEj&vL~Ee(GGvZoU^Lx?(FOQ7;7n*G_z~cJsv=c-eZf65_6S zm3Qi}OVZ(RBF?*Va4wkE@Z^v?wbefO>aWudP|R>w$aUIgAH3C@6#GaXUJ-GV0&K7T z5*>am-mY(OnZo8mv3U4wM{E-7M(hgf zxR4@M)R8P_3$SmbV0`QYek}>RK7eUWwK25j$kY%-OR}v{cSC_~Q#4g}WTwQckshgT z)&s9bR+)Ge&d-@Ahbg+X30V1V6Njw47Cbae`DKl4vYl$fauui(K zCgf~WaJIRk634nG>{$1;$Yb5tWeFwNw>;!nQ-a5u6I}=1x7B*0vVU6y2dD?=_U(>5 z%q;Xu!Tc>COPpvZweQ=H%~j(>ji7>kZ;3q76o*h#(2PXS+i;?#(p)<71^67@c%YTjd+BBmxQTTi(=sarf@UGS!IjAY&toT$fDvE=}c%T#z~|Tz@yk8^lwGl=U+0Qo?~@#;I#*Pq&d!)(1mopFG=YZ>5SMZ zzMNQ#_qJpTVA>LTRpyMS@PJcoKU_nTxfvvC^8b+pke{hsyZxpclOOzr|WdW#PtL#G1Zz~2ng8}su-eJ2{on*({gN^tpXz3?`p+rz@nxkZzS#m+|2x8Y zfRkVG0}`zMPtX|5^(hmqrT#A{us(AWuomf~0KgBNG_{0lDd4&x9Ih`Yxc=URtJnV@ z1=sP|z>wRRc4lry$M_c?~a7) z)8nISAV31C_TvLV@8F0;v4%gvzYTEH`t>M?0VM$TpI=njquEUQQ zaLo#b>z=@mC0vKEOMD%Er_!0;uX%a8uaM}Rx=NV99sWdAq#b@*0r#5>-1gybnNoA< z@DCMme;yUM=GR6N2!C+eXazCuH%7z%Qaa8g6SnCiDM}(34`)XT)wJW`>`0A*?RXy$ zjkHEc1S8AF$JyaGOW2OwD_QKw{YotvVAwW{oFLeySYbOd5|z)6JR)H`a!$f_#A4Gd z8M!K9J97P2U_0``o4|JD6AHGUx5D<@H<7kReql`8Iu30Acr)1kCjz$nGRNn$BlpB6 zQQ9>Ze~(W6$=jTmCzpi<%mx4AD#tV}@8D#EOz!GLlE1T?lLvd8GQzT3rjKyBTtCw( z)3Gj@zD=d?@0RJ4s{C2i|Entf_N-<46(V`^`;gKU{Nk(5HIRbe=6B)KNe50Q3F1_O z$iRWS(Pf(5=EC3UaXLIUu|~K(RHwOi@dWxMeGIZ>-1w79o*g!oD8WJvXsxx0RM}b@ zKL87m$mGACA%9%8os5U#K79DgUFJF-LhD|$HACn_c2~Ygmw~vh9N96&vxYYVSa#2f zOBF&tke}rYyqJ~bOBMUeMNGZ&gMD=l(zW`t%18ZO83ynH{jUi6w}t`e&$l3EEicp> zQ=%*VT>l5pP~{UUcGM9`0Qr&tIzRxuGUhXdFg16a*wK8YX_T2^0MmSR(PKy3Xr8)p zVn^p#WVP_v(WQ}E#dZVF8?9jg9)RVD{zaHLK5N8N1^O9!z5`0RIHJ{4y3Y3!0dF15 zuWRto-=B}?M>zjfI-XD9nfuh+BzzaL5^|v(Mvye+52^%^>+zU|M-?8WL91;!9z8IY ztcq&CE%UvLUJS?Zq%@oOZdklAzRz-{=KB(LQk50H?{a0Q@B3!YOrP?T`hI2hO!56q zlV3o^a+={!Rv@cROJrCZ=N4NHbyNRmgSBEPRH8KUcdx1D9$lYZV)wUeu*4hZd704}u z6>x^K0#@3ZlwEp?tyX<{)nc2B+yk&1YAHdx^mbq+Ik@Oxq+co9LlW9H#8(u0=nQZ7 z$ltIj$D;&~!k{C#2#+)j%ZDK*J9IC@F>Hh!0Lcj z+$0Te)2Zy+L}ZvC7j^xpt3_REgi&2%m4v@z)<*{QYs#!n2)TG@H0;w!%H=tXTn}ug zoa+nbI)b@2BWJP1r#Xb$A3?wfXG0zDuQ*t@$YqR}7tH0donC{T{!N1&;A5wJdTh36 zc#Vh`&8;FnW_GJ^$MoeI5B;fpSnxlai|3cp@%%hJMU&!tLod!^zBlxe(o+AbwPD&1 z2O44x=BB@opC94pPw-UrKb%U>4ajCb^*xJwJTR#N{IAR{@`D_%GRXC&g>t>A$W@2C z28sfyPMH=cuT_zS>jf&gQVUEq`G+UaqBNI2PE!JlIrRqCa+(p?s@iudmlv22+8;96 zReE5bCRaGkX=UJob1!dWY$BdiD0xy3_)4eZD^-%OtOWm=qWDjp z!IpHz3QB_PVM-MC&=X`2lj%Y8iZE$ncqV|dV^AMfoM1hvdk;l2g61HB_k@!_2-nDk zlYfsv{^6~2gSpwrl~#b%w+u2(9vFHaq`pPO6A{-Nq)a5v&(HGng>tZ!S9cq&ji0eUQ)yUBq=6-dVdWOeEt%PFK2&Vw}XyGQy4(fnGMhKty#F&!nSLHA4frCx0Lou+YBaIx^fj)WvHw|0sZtic#RVy( zp5ON$2&rFKE#%q#YMwm1->I|vvnIjva;zzQ9*F6LaPL(SNtx;!K2^*OK3EVa3>KLe zSB49p~uA>00^-1fm3%eD_D%gr22wQS~Kj@-<_BDEPFR;4Pd@5PDP8NwMhhaq4IawVb)f3SQN0>H|>)VfZ!rlFOu(sU`iPfd=wscT!OAkHT+vw5MWz==4Yvs^1d9563kk`tgnetjW)Mfd);n3Vp$n;)yQ-oX+ zhnC1o;?R0|NgUc}xg-v4xJ~==Jf#yP)L#j@7tAn6Ym3 zTVf0k_Zeoa{F`WNWruH*7;t!<#DK#aEEsTj3s-7~@3ClWhj&XY?C_f;CLGo+TG-)Z znjCqV)9S;IIT!NuZ@)DyY>KUOVx6ib0sDC}T&KEK)#tfw5l{HYvPhh3p3sUBuDqytLdLaI zhbw`RYoWY6!^+EFSv@I~D0<|~B1X|87bS`wxyoo!bmT3P2bBRKkGy*hMB5lsw2i`z zs*Ze&UIjxxD{=A2=PkH+n35 zqljU^QU6t<+R?vTQ0?e{xKg8d5HpneSdwIW$Fd~m9Lq5=r}kK}#GGT5xAxW26x&P_ zb7~W?R#OP(dhEtq=|+g#~zJ9kYgW<^8HY_#U&g;QgG^{M?V7uSqZlE1%)BUek@HS$9^F(5AhHi7&^!5?_v|Sn%a|HdkuL3r&2P za=ex+yN^#dduAVR=E~&b9cIs(PxM=3K?VnDA0B zlGxq{-LM_Gxxo7th4(d5BV3PMnab7M%9iPu0m!F9h`|dsS}01P=xty{545pP(MASn zqnr#6lv|>5#G}LL<@i@5y&V6h`R%>?_{$;m;Y2 zxmIUT)9MQ4%^8M%W#%wtm>u;*6h({s=UUY!E9dSG5@sIiD$%NP;cC-~6%il%ofx(f zYq*wE7|PeXLnVxoU~7r>W4|IcmL2;ZNO?2y`qp}S%!Ibny@2?6cbl|*amuf3xaY!`YCw_=m8M=i7(fH&>PgZe$#?KKiPpt9Uk0}A8e=# z=B5R?LM0w1S11nFl`@Mp>R<_vVs6blAupQR6Ec3a_rxnEk>{R_<;v8P2_})ZpUmUR zc_$0Zo+T&CxiaTuwMF_l*+~SP4FWC`bD4locE_>Q>ok|>mjrxru}S&aCpT*3uYw_| zMy&R7^JX$6l~@f)C-0WL=HyN_ke46QJj5j1oT5T3@N)BTT(Zcs49q`ySn{}&C!ERV zR!3>8sn}|PXp>vLOj}J0+3H)=R^MsznkgqgF4^eGPg>aM$*0v4U$sKxml4o-Ap#mN zsU`ku;e)4QXkab|s+USUHHil1SqGjmpc&b~zdk<^(er((=Lf7k zpHMw5me$%+-;lI$iY%=rgugFo;nYvfo(-q|z?HL4{mJZEaOxjinQ>ZJthc9=xU%nb zvc-CPI*TjQP8XOxyHD40<$}|ei@EGHE@q7AuyK&@`yup_y*WQa=#eZOcPW57j_@FDZy)3<;rAk0s3JL^sA8lZo@Z!(~;YW zeqPnDjrv9L3+cbpuL+@@zFfzK|=n~UJA8zV)7a1*@ zy)>eqM`Q>ujlg}65gXKq9E?Ce*rruoHq~KfuSmwsYyeKTtz%;^q=98D4R|0Is9Xwi z*cJ6#!~I}JUZ%{*xiBM75v}MqNA;UxTQjkT>-1AjjWOpl9D?xvLEi%0SdW$&q6Oa~ z*+KE30>zZjsE#bN7)1`r3fg_SH78gskJ4HcELJNSMiukI#zwIyXP8q(DW(LAg`s0h zP)rS-Dmz##Loqj4oE&AUMfSmQ{ek*#Av`_mH&Ch@;t|h27rCsUcvNH+lvIw_nH4H- zWku;{)@28C$-!K@DU2EOnK`VXcE$brLe1#>;`2iL-DV#g*RiR;01o`_^b$Y|Qq!v#fi4QoHEy}lT^y3l^%9$FQ* zb0(FE=97c^AC#Ess}Ox>_G;dslQvcq1x@so4kLGGFjp4L6-244h*DP*%;iVvR~#|I zX2}%=bEQ$-0Oi44Rg@9S*|c_J2_#?rqtcUn<_Auh{un8}`p=whF8|WvZa(uXuAFh^ zHx_sEncvI8{Ztq{@lFz;+eqw<7rkA0^azKTKbs!2kkg+)wzbh{nYD->y^Zwf!=nw4 zPBe6}cLCyeTPr;}yA0pMtPa$5u(I7DW%9G>JxCMJX7?doceX&vk`)u6|h~$%%;M`|=vd0&p3(s~rSx!5om}dfw`hl z4t$mdCWj3Cz8d&b3^XcbG*`vhzdF}IjyU_TNI9Yj-(K*IJV$@DJ)FD{_isO&%C)b3g=ETauf1g{=Wa5u2`;xeN{0VAIAkb zUeL+8GcpErkz#1YqVL?NLV`{zgUa)?C@#X>Fn+=8qE#}2b3bv)^yf%v;^ztIDF52R zEzbQ`a*J~>S-8cyKgmKdD0Ad&3bBjXTZk|hZ3O*yfjbcW6LD{m#C=|LF>#-__b_pv zkCViGK2Z_(g*GDYv?t$V2_8J3TMOczuA){lgOAjp&RodF@o7E(e2t{_^Bv(KCFi@s zLrTuil>~Htk%jWkZw~heoWCR7BXIs6HE^dznLEEp@F14+pAQdWIsc4W@j2^?zYGuOIR8R;ILG;y)QVPx^@1~;EnSEUXG<5na>WZ7 zmK86Q(TW;Y#8$bvf>!icSG-UwSG>@GfyQhydc5pHzjHU((uKtnd=ds(9l2)Y`c*Ci zIl~RCl#vo?1DuQ27S-BjTM~_B?a<#Wgm!^Qo~ncl521Z;mF^YF-N`wGjNHjqLudlq zSi%QGTP7JAwXTz`w2N&MGqej2Nrra8FYRCyK!Y8;)8J_Np>CP1C>+flEM|muE{M{a zuEM2hr#EAN+Y_*pZyB&)vDOo0b)KL-(QS&bQJACqmYCyRp!y5{P|VSc-Y^|QW=@$Q zO}Wryoo4F7x7E#b9R++ya7=?9a26Jno)D?#@))p|RSXz4(;mv==`mIqk)#Re0ycUxL$G!#giNSBvn@>CqVI#UIJ= z&Wpd56npVcGBo4j%dalHb2RQ&!aGMZB$15fTf#d>r`{yIb9Cmdgm;ei-z2WJ>*pNp*BQM3#XT$ma=yTzGfAoiv?~nf6 za$$`AC1T*;A_o3P4!jg=;ro|Tq+RP$ma`XFbScWGz$KFJ&jmkkQMoo-OEk=CWx?~( zboINV%#$g%PUWW9)=i9Vm%1goU7Blp%9Af`c1Dk(%exsLZArjxcB|be{&-7Vv7Q$` zpb*sLab|8jq`h=r{>8Iag|x|{@6uBtNSkjD=WGVYx*dpIC2{o9vrd_Q3n@+VT>=ft zKd>P3r5{T~zVtH-B47HYEM!1&96blcaWhy`2Xmz!iP4w-)W;Zo>2I?cqc8nSV)SL3 z;!2l$2&1zSgc;*;Ik5={T{Iys7hlenxO{m^I7(iw2}jAx4H6|U&$OWA<$m7DhxJQI>*B<@lHeJ~!_3bOKmDqIU{{I=9t^{5kHeER(vFXY=3pQPW zd_JCV$)bUy)DXF7Hk^JmDn^^ zV8N!bVhc8nT=7I;(^zdcW7F7-UdE;|^@;0Phq`UY&Ji}H-&kh3ZO7&tf9!+Nsd{{z zDi~WOacb-};W#yRPdHAE-6wHs>_!M$X5zN35Oo=Zpo=F)(6O&d1RZ{zZLi+p zl<8KaG|6iSG$?OZ*vy4{B{pB(rLdU`56D6mFmq_E+PH4@?@BG8Q7|rFz1GjTeD%7- z<*VQ+3sCv$6YW6dG&eo)QM$rs^(ZzTk)H&WUHu~M9*6K8FVb}N z7t&*U^?8fO_UiArGV|)6Exz@u{|QIwYcb&{eJxI+^tD6_EnLfv7?>L|uv87KvJPwr z4;Z-C6do{ety2x0WfD>CwcEI|_u5jtl+kkySEgRuWN|KElV+gV*LIja3$ESIl^NFt z%%0WP_R7CLa&35`-&3fu^&+<(q*=zKiCmG&-EAwf{%w+Qk1GNJSL=_{>0CRbevScl z0p+*Mv@Kz(1#vA_xfJ9!ipmtqtqJ#PM)}m`+I30J*WPXZDbQ)xzUlO09jp5>Gbllq zg%(RgU6+NbXfoOf|(f<_an^Qx6 zU?LBbSDHM+%vtVQnasl+$MiCe7J6_=A`A;Wq+Fe&C^!a>dUmRwGHi#eHFjwEYY1DDqB;AF;R zPMQljX_Gy>^EsIf9xB{@1Y&5t< z4IW!;A{`q`$1fo9&mX=1ukz=QKDK<)(2p^1?Y-LV`gIYrye2LoMh`dyJrB`S^u^P= z)ZkBwB-%QhfKjqo;iLukX!6ha*dCf@{I$A7cPjVD5_4!@=wTb|FdAcAGdyyAT9sB` za(1%*R=QvMXSmfEp4B7D08raNV{o8nM!)_xA?nv_98%_%3^Up8qI`UxIeL+OPm0L0 zcCZWE?nXin!iChC2>?N}{&u492emliwF|qLW_KmR{TYu*l3es?a1A8k?=HF~>F>0= z+QdBfu2c-1rN0Azo$b8lknU1C#S~Ftcg0a>n%|4X8tg7FO%$`)C1zs6RqlaC(QY4b ziOKc>4YTCJ`M`fna~A$K)KvRGa*Y0I{E3tp$1Y8Orx2U;XSFnuU=y1DE+IDS-;dlk~UPU28>dyqq^fe~%D5^nYk6I1~?le2MDqy9V_463Y2JnkMQU zE)Vd#(khPlzea8ZB#!w*f50_PuFh(qJ3C z2EHbo>bl)!U?ot|JtGB4N?S@Agp)2ULlno;P74%yp|)+FmPzwiYG>&0r+Q7ytV^uG zP3e?Kkcs9TJ0uI2%S}6S4CLX)@nTGz{82DPuG*}6P8Lo_lDxDA6i+xZbxj(46x=8A zjxr?ack>oKyEy55h&kUs$BkyTe4U*J(CA^8nT-m;&mP;F^Ct$IyaxGLfyiNm`YODmS z08tgGKhVoB&)lT8CIPbE49#s+l{Rafv}*}SdNjtbRQ&^3SoGJ%ITAc}SA~el9MD2| zNvi%q?y|Vk(uEgU){dlc9Zx)ci#AXH5aIIh-BeDoEn@o37PIKU?0XzymV>aOME(Am zhQCHi%wT($Vg@n#uX9`G#rS61#XQ1q#)XBnCy|HuTdrPBBk1ujyU}C*1%_P13?xM@ z8t;foNLuTVbaXW(0OIIN110M%=43utwxeyi9JQVSt!=5}(%t1tDVh1&#B?~C_zG}| zI^qD>bDUUfcR^yL-7~!`w7ZI8^vfWQI>$f;q2K^XT5f7dNAnuG`muAMNW6Zc5~)jn z`;;vLh$S-h52o1&K0-Y*gSo8WBi-6C33ZcXE)$P*rs3ct(|AB~W1UU^Nr_B<$?4tt zi}_waO#ic&0z|OyCGp(T>zh=HG|uO$KGd^uQ^iKqq{x~K-+wE+3h+3JC_K3wmp$3b?Oj|hNu$KINoY$Ofi@5bk`_vE zcZYBk$n2&~&=hxvKnM;W?(XjH?(XvbH+zyaMe=>Qx1+l|^Ut%9?KWs|A|{Pm3xGB^ zQsc+myoSe*xoyJuF?ZLA4c?68{q;c7!T8o}&?R(Q5~Yzb3?3%1!qlPBupi>U5?K6Q z8u9TeO2*xbM1zysKL>naF*>Tywag4~I?9g!EkLJJAG*c9PHmQhWJ?5Wpkh6J4N(Q| z+m4?`{It*yDl4`@dFxcEz2P0U=-!q@_wMpm@F5|e-PEl^Y^5-slq#|ThQrR_vIS0x zF~d%>2Fx_f2guv$SFA@3Mt(~2K2Uqm7|cX@kwk;Z5v0Hn2eLGg0#VW=ZzB`&2;D_$ zR%3+_;3eCo;IqGMpE=Rb0pS>oeY-XoSllLW7otY4)Pt%OmN+ARu`U!Aw^PZ2xy~WK zXu^ZKmTm2%ewyPGsh;g}0W^7`o{VxZAV|z@uPM}I3xGq^%Nx?MvrG8!@ZiumFr7pL ziPtnNkwhIK`Iw#zX-Mybd*{&=<&5;oJB8?wuj^%CGcH>+LA@W+MFVu4P0_DqC{stZ z16axE>yXGtpC%9VV}l(nKklriMj&<|f2{@8O-BQV&6GkO%%-nE#Rq4p_{=s%^BNT` zYF2bjyIgIHqD^xYZL3yvUWKBac6ec9mAs2Adb3~mqLnKBxK$V zMc@c(jZzGPR`69h3>Mp{kvg$0UN_{6xB#7n@*a%qQ)8N$i^k^Q8j0GR=5eh)G1C)O zw(iAR^xCaTpMp=@KbwT~!kxy8)PBlQWVk9Gm9p_N&fm+={Ip zE3D=RtqP{)R$DLgGHY$c%dB;kE?{k#z{{-7IdieKbEi`O3qX8xOOzE*&Sard|9chL zw2aBp7A9Ml)&UBOb|MK_ZR2er;Zhd^ph_2wES-nE0*K2a5-7CD<5sWWt&ec=H& zY15g^)8&}FpRUry{DrCIEHGiNWQkJzKm|&c*O3$##674B9n}mjx7fu+l4~%9el#b= zfHNhFO`Jns;n*)D3b*Erfl#u%k+@s3yv75*<`Lm!Qmg4wj%XxVTiK996BOGzR!#y_ zopu~-t$cutjb*wE&yiw32Z?dAXMhHsES_-m)^j}rN@R~#*lcNm93!^Wl*pD8e>lAo zRF~)1|FlWbuhvxbrv^oT zZ)IvG*}O%oS2R!xx~`eI0JO;rcYwB;<+>8MHMYQQsZ#=XUZTKVsP8Brq`_hK{R2P9 z@(giey6AI>ph}Eca4wH)b%|gWU0xe6K4+7gwd|%w5TmUbBsh=3p5Ix=WFeDz8!*XO zT+3STRtZ|~E_x2go>2wch$`4oRO$!JX0nW1F(_qCJrs%!sIiMdX$#BF*hNN3=sd0vpH?|VvxY$ zb;?c|w(XQ-l%6F|O0-kX(VOKXLUfZ9c9ATp&WMeKS@_a^uCmf&gRs*-z%A1)A0;b5 zUKNB?>oqA2^c|Pc2+0ICk(1~F}k}3^-k2b}(w_?7% z6ui28IR0t$Q0|7si^qIT5*3;t2|CV!B3jg z-k(P5&s_(wq2-01X^7eY3GF6`_$C@eC{m?4bjl8;GgmC8$P}lY(wF8ap*3|wdFt%y zjZw*bjP>2^1C8yt4vIs5s(D|ZC>1owvcw#6eW0x~(I`;R<9*G&zo3QKRs@~4kRiG>CZ$lL^z3%fG=DkQlM-6_`K_f=6{DvFKkR$ZTh{tEew!2L=V87ZQM z@9Pjv!V6xJ3zm?vAL(PhG*Ka+RT+0NSexN#7Gs8t>&oW{fDO7+F`QXoA3CnW(1-bI zF5+w*A7);LicXHygR^c&)%drom(L4fY(RX=jWoZLoLSDe0stT0V2Bzgto(`EK)rl{ zIMJ4b=58!UbUGV-c0+0;HU^8)keoLV*eZo?7%65n03lDSCfVV4Xisp6=Gr!0H@I7R zgxr(s!kP-wd!j?p`t#+e>NBr=kwM=fkJXFhOGr6|Qi{O<0`U7~#?E-xiRH?daW48* zIyQW1X&lcs9R`1fAEh5K$N&c3xKWCn++%*{mE?<#^d(*qZ{G`F&uGReV#t0d*{eH}-= zKVb0I$TYDTO{`P=L4~=by_?Tc!K_%pti*y1@(sw24~wH3HvA-H3vB~0Ky&QyYsWzf z=ShK0=g2pS-_bGa8jlPh*@2M}ub{y>NQToi1u%Jp0Uqp4c=sZEb5PAv&7tw&1@Sgm?xbQYaU>DC;! z#Ivn=OmnUI^(wxDwPc^wRg>#Stv!aS)#e-cEV_;d!=o-Xg3$_{)|Tslx~#2xd;&XL zH*yEWo=(mw&0b>P%a|uRyPI`a+@I{6zY&vl`k1W0l*z`MV~Cf}U+NL%z9EmO^QGZu zh%GHBFqt+JcPrz{uB@y@2Ps^ON!t7nM=IU2s)tF&h9OSdRHgMRvQ%fXHIwiT?A4vM zs~R+jO5aPVMEk4kgPgD6Fr5d6t#ahb5vKXJ>X9Rl*XPQ&Xx6-!vS)z<6gjmFti|y` z5dsShGOw+24yBQ+zt%}W*~2Z;d>gaU5yZPiSs!sda%L3(@jI>_@B{K~mZG-DzXtp& zjHXIOa9!}dgZ!e1yfs=n?p);8%Ea8kh|Y#b4kgb$oC0kgCBV~zJd1lc@fhb`8_RbH z;qtmD!qb7jFpyD8z7j_cm|h+6F}N4}%E7h}w{gQ7#l1+P;4NKvOAj%J?b_tK5YbOl zbA`|zRd`bHpqLcO!z4(&WxU#UWLar~$FKZk_2YM6`5vD258WON1$b6WKdJ|=MBX5R z(2Qeu%W)2c;&(#>xPyD}vj^ek%K;1F_sRvUPd=#3ewC!Ojalh1OG0_fIm-=q5~iNY zM1@AsXmH|I5Gz+I=9$6C*G0#nVGAW@pL5+{v-`J^ zXlSICmLCa$YF(ngL0?n7T?b)`j3KeFhb9q9p=F6elqbrT)WP(BJpCV?5fBM~6$Ay= z#jRN(FFbT9*eD-qFqp2_V&MMkC{u2Ybz4DF*6mXBHkUO8^YZ(8omd!-+r`Q zCyQ|1rj7*WK5Vk~GIVTxRoW~yPP27@p{dG9rMH5*=`x%--1Y(a<~qvad2(V^Bl~pkFm>h$~ZHakC zx>DO9ZvlP3d49T%zNhtfnC-*(<%|zf#>^=hpNM8OR7U%OzN`YBZGP3Nl<=>cK^x6) zb3o@>qK)INq!!R#D>+BU3s}FP(S0JolaSU|^VEp`Wi#b8ZvzQ;bnti|E~xb(I9zJ5 z>7XKO>lAIOSG27`(RoeCTr<2*JAB`3;%+U&ef=KzOb#d{x84@RTfjc>Xek)h0Ssim z(xP>5GrZd-itf{^=s`;qUA9Go{ERrm@Ub+8LKqe8=&y2!6)Y}mR7&`NN+YzW6(RyQZQ)+3)m69XRFE;lFg3nikyDULu{N?$Eq9vfo^~87bt9kLq4Eld~qG!}k0Izo`6H zevU$K8g8*ZF@LB_%&^^}KbjfK9pNeh8ue2?f!WF)3^`tb;71%gZ0kJ{w@Ro+LV&HG^&@M`FUc8c?rG5d7Lqm*fb&-HkAtrg ze!Q`tT(qBD=@d)kSKva&7;yz<06Zw$NkBGW;_@N|hld_)NShv@DlkD`2<0SsX_=E= z~PbgYdX(ZF0Y6r&O}>Sl=Zsl|zDmN48ZEe)FH7IxY^`5h8{l$h(Vq0EW= zWauzITMDGmi&|I2qe^dNmoAgv6Th%Z4eAJ&#_M_tl)|T>C3Asm-+tuF`GJP2)n@qA zq5#r5O5lTpR*DgzsjD#7`tj9)PSGTPBynqPWY|Xi^);2ECMcXLf_D?&3dWS#X0nz?FcXJ`wwuADKZ&7d47Dcyju<2|? z_ieN(t4gVBucZ`zr6>CSB$Ilk=<1}`E!|%@BUjp zmedJ0669mcl!hXifu|3DG{_3c=wEV}Rh1*(mnL5vTP;n_dR)a2BEl$EdM2Z099{9`|+=iJQHIQL9W&p7Yv2xKdXd>2TE?M6md)m>m&p?Xc&O&|5SV>|=+Fd5bW_9< zr?#f(wQ(U|?^5`9dSlfMFNRh4rF<2B%MQPtj~i^hZ70Z*9p|&~+I4M%XFzw=T`KV>hk-RtqyoemSxfsv}PqMtC6O*vtxUv-L_1mOrY)?-QS6B-C$vRd@gsEK|I!@I9i z{sL#(rPc8&GN)BB+rM$l0a+lgH$YS5az^XM*3P=U;?d5LPxh6M)!_Z(imq-QRHfFU z9NehET^zOs%lV?vI%LgU;L&ujj^@eKo1UE7J^;@@ac$RgCq3FF#bFGJrcKIuw`*Fi5)wKgkX=&?K>z3vh+wSObaXsN-$?d>3sZO6WQaP0c~tI#1TG-Q;@-@!zP3%wEK zN63KpMWn!o6M!?t4=0dq=_8{M8`8h(+x2Jj0}WqX1QV@)c)Umnj7uw^oX;Abs4&=N z@g&_X-K9`b1l=j!dMjOr-tB_c08Bu$zvIIsV3P7!4aJb>WKwM(pABc zTvafI10@`3jFjoIoaG}mUf%vZ(&YVzbA8g)xjxm{wzhcMmk&ldz44=Y3~KY8h*gO! zg9`1o+C%I|`n>AP+Dp9l4pY>$x7XfKpUu4&KPKltefeNy7!MLXXIm9-`?oJ2jGXFS z<$xOlSAnVLXZOr}u>Hst-YEy$`$gZ#)5a=iWoJ!2A-iYhFCUDoxXGO(8n+;JUO!i) zaM%8{kbyVyy8_;*gZnUJG{qhN=D}!c3vY2w1YRQM3P!UP=0?k>V{UZK>6jaBP|z7| zO~BmfI@2*Xx^Oz?M*Hl7i{qFp8y)c00bZlq{Wo|uI~G?0RHOT>22{BK)f6a=E>ln% zwY>IjdXzu)pP;nr_kl()of$hbY@{E(=^qd?6&<4w;gQM?ud>nM7JZ}duLd0@djSby zg@oaeZ-Io(6Ob@=tW0MLAV>eGn!q~0T zkuY|z>d>)=6Ob_W;&dd8y*wQWV{h99Ka3-xa_n=3gt2e`9}-rI|BQr{K81vpp#&tX zEdPHne@4Q}%~wIf%7gw35>}24Pe;P|S)Gi8@$(fD#xGHPef;tSB#d8Q z1tfIX2W-xoj)a`?JG|U4;}3J`1>=wEvBd20XY49pqD<&|j(pdcwlRDBeSO--?D5Z4 z*N=Z2@A{(gpQ-CX|6HZ(ab+KFU8)YZ?nT$PRPn(Ym-xI62y6RH=#XP8-tCOOUplSt zFUeAUe@Q{S?~O~EyotvtqnGU9%zb}Jcl3Vq6L%szXXyJ&`t82A58I7zDPE=TFWGTw z-_s6}OU!8B7sS7(kl6QV-UG)^rLJFVb1E>;-urv$2zULammZ_K{?ZeSd@M1$^jeyL z>03k!_^$Fx`Zex6CE*B+OV3qUFs7dy(23v_R9rgAsL(Hc(opnmrmYis+^-8K!g^el znJDGRtcfZrWJk77%;v~N6K(OFMHBNmGJ9ejI$WVz(ynRf!^!~#h`>>;Hrrq|q z+SWn%DZ-UJ8tA!eupPZQv6okEr(fNkdOuarH`7MkiNh3_CWgJSZ-v!QoayBcVgK8% z`6bT7XZlvy#8qCk{eAU&;5Wz1qU6-i?o8a105!h*%)8v@t+Ls7;(0uO=ixo}7WR74 zH}O{#dE|vK>?`e`HnVS;co=CBaCxca&PnRt0^ciNM7b7}V8^;V6<;#9aeCQj-JnY@ z`&!}jvL6itIGxNOoQ4t)Lz_&l12)@zj7`iUuTFO5O{OYrPKLSCn#pPgRp(@F9BH|e zEy^&QoRh%0CfA!T?IwGtOS{Q_#knT8@TSHK?mk`GP3}2e+D#s47d$l1@`@*=w+on_ z9Qh|q7b_$$!e>|8XOe*JNqFB=Z5+oAbHNh~{0D(Jd9lLr%!v(t}vB$u5BvH$^~0Bi{~!W{wRHf%?Z!-HYj^7Sq6GAMPi_-%v{f z1QY-O00;m|m0DFFEq!)OA^`yHmIweQ0001NX<{#KWps0NVQyq$a%3_tFfT`MZ)a>} zE>LoBbZ=sHW-fSbZ0sFrZ|g+xI}-oF0tpJFdF2%1J<9Q*P;op&3w%Hb9B0#*I(G0n zO#|Y;GuN)YcG9d}rwI=b(8Tc`bL`CQ%7&yZUwAUk zBKQ-)KTkrf)ohfkW>04D4Th1gl}7e8 zSAm{|NfLzEsSaj~Xd2A2Tm^qD;^;bA1;sQ>gHIQeiOPqcCRud-6dKjWepC)#K4VBW z!gjV9wjmC2In9-xX35wS(#t7;WZDGbD7#U?avB3Tt85X#(*-aFb9qAj1)GD)p)pL(iGM}0T3})K}Ry$5SGVy5y3mD zg25(P9$ctsk%Mx$2q)?(e2AkkamK+_GyL}R%it^r3@)?$dgpX_IV!TeN49*L0S5C$ zRDd!B$d^GmRxru484>0xzEP>c6Y7+bLT+!b1HE1sQ8*xi%@(>KDvqF0HjXDTQgQ;k zzyyrU_<(Qx3R<@xDf-=ASp0l8FMN%K?^UtLQw`7r3Y%3hwDWm>t{JYCr0m_`?>Cd(np`PgAK!b?>rFU&;%NXIao(DD&TVt zJ3ipruz$?H&e>eo5f#ty{G^P&!(8;RtMQHHov^05mbTCn)3@y_B^!--2 z;iC#?2JZ7`Lw>MR&;@c?#A(Io(=_-X(5p0>=2@C8bkbTroKFJ1AjvsdB%rzHA=t|> zD?tg50h3^|P3hS0(-U=a~a1V;nAJ6b@@H=iKo8r)=DC6`m27Pfeb+o&X= zwSJjht8~u{7yi$2F2~)~UsNX^cU^r91Hg0R&{|I6vyk3`YH=S=V7IgSm#{ke3z6Ns zxg|PruhA4Gcw~3*-q>Kl-5SFS%503$)SN7G+_K1?I3f}mTd8IuIsMe_CD*np=eXG+ zf?N^6#tFTa(7{c1O&zgbZ({Z2HVg;B$?a$~2!_MqYpC(jJ2GNHHD zul0g`by+Sg0C;dx@nfr})on2(W3-JG4A?G|IQH5A3oIHa8B7qYB6i&sFcA{=&QPTw z;{zmUIG-mg_}q<`9qV(W?&XN9NWhUo6*(r$kD&-gaSGj%RV*5H8ETPP z5W+x9(@x46q+FLi)Az7YOITo zdpocr4LhPd*)Q{v?D%&wA5Gnt-wu`)zEH*I5am~S2w^EtUZ{kL;(}WS8Q>LXY-8+g z8O5LWvL)L-csBYSjG-MMjiva@PqPH9Ei%tuK4&aq5dY=>aoPc=Y@s|w7vy<5Ulg8r zD-D~nDf@lM4zI@qU)8k0JP>m~XtMdQpZ~E4G2iNF^J{~3KeaUMvKioPUe0E!R8>Nm3ry$77S5j#J8s#N;j>1xRJq_n7Yy#>fMTU( zoOB1w3gkUc)d3JVPM$O2CsyR^tX! zXc(Z0k4wr?bHU{@W2hZQbUI>h48vmsv9?d2EDcu&yVKdR))g-AQ%v2(^1jHZ@;Wsn zZg0VPJ6RDpk@ah$3h)CmJ*7!!t_QfI({~BAt9NXlL(*sC%u`Y!$J!iizXA?*P{frg`MZ`?j z$vg=oN$OtB6)y&kI?8@ouZy8X2^?1dY2@0^Zaef>#|4gs66(K7Pi}8qTpQ( z>$yb9hz?CqG%ReIEC{0q+~2FYLa+p}oHZNH?blop$4=pS!k8#5rXB-!wrGILetc+# zI>WAid-J77?o@DS|IWS%=iJX*qFS^9DkSlr3PbNxnZFlS#6i?b2b^tX`C+2M8})3i zeDgJbnkv*w2n#hOR#<>9JSX3riPUG%BL~pOv4-pb_{k(k$t&vw2mBi*OFT`4>Xh5# zXzEqWa+ii4tEvyg5a0SbVfbVaKuAskH@0t4l2`SfP3q>ngLvj+@AUy!+`>oVq+SqI zHpWQZ5R3zaEL|jt-FcO&kdcT!QVY8~!Z^-htt2Z@F%CustP4^b)RY9pn=nqmRrXNG z(va8ZyDdOu!NS$hKQ%*czE<-B);v6h2N=-J=p+Z*cJwy9hWRuzlR~ITCFTlbmfaIL z<6tXXPF8mJlcxU7c4W}8ijEm1P86};vq`cc8rPCWcAg2~17;7&5&mJ+`h-Ap5YrHr z^k(z~I*E66$Z0*2I-Ae;#72W%nyGOdoH3beqJ(O~$LNgb4L-NnvWN~eMPs1A% zm6)pNnsl<$=S`R_6m3TFV+^Nip}Q5?_8!sxK6r?U_7ed6HNn?lr#=mt)>^?5p(MM8 zoiOnR>;e`Cvw!BLV)5mqX*h3W~<&jCbD`;JW34>sE(eP~DM%qi!TXw1pF$-_w z*f1Rnu->A$V=*|Rtz8-2q5(s8K~ISkiKA1b<$tSK$$UgXgO(b#;ma5XNHX`3tl@uy7$O(AODM!2_`> z^P>$l`cHm~G?sqh119{z!e}1ES?_cti5P;%B!%b!E9oH%TxSsU6mRa@IeWlzNN0;Y zQnX^T1vE|TLpPn7b*liOAvFsg;oBeKiH}7<GGOAZAZJyDaMndN&Ug}QQ#6=NIN zW+Un2L>GoaCcdHv&Op{+0~rrKkeE)x9m|L}$~STAF1{=YTF&v!lau>W(PG7OG3|o1 zpT#)DpKF|OxU6dHgsFAzWqLPiP2dGJ`|Rted1{e410Bu6<)F@a>Er?MFX++%Dp zz@GJ@=!yadd)hr z$jmwkj)B=ET(X36Y&FSW+E<|N$Lq~0mPSkX<#w(FvA*1>ZX-oR-N;1eDed*YlW;c& z0zWs+c<14CYR$)BNko(kn6$DJc=E`O+cOQnQ|j8EX85)?IXWo_H5T6p0qbkCmnAa7 zqAS;%*KCC7u-mDSsrq@-gh0Wm&)h3%u4r3F6Q3J05f~W znbPU21@H}47~s>+GjKpw7by^~u^%!=q`2!kavo#XGmI>&`f5+ID@+wymu^L%!_Y{G zF?48@?|^<#w;_aJy)ANkBB!w^ctc2iI%o!-Jt00uhaiv&B?hme*E((HJ$UHiI-cV; z7tA^DI;hx2TM~#Z%DGIX*28Iw)ct)Smid}g4s(ubq@-M(jr4P2yUvSsK;pd4H8M&L z)6`S0r=$TIpt)mtdPnoN`w9yvyRqaWHC=TB27xA46&@od8N0ZRO_7C;ub{^2oH(Vi z^1@9Z2h?bQ9j}B8^b0-!>e&6@Q5{XuL^b`HhhN?X0Ra!OuNG8HNSQ>jQ6-aolTCm zbvdsT98r_POft*ks~Bi%6QDMZQznD^6yoWFM9AIWhsz&P(pOml?yCZ0)z!ku zl3&*7J}f9G0a185_sm&CHpPh-UzSEp<|`{tnU_@4?J`#^Ln8QZ8Dgt7qpv>>M6~y1#gf@ zqBm^z1DRE8j}<~1ScJ$)ucVM=!(42*SGdwM+$VB_8H`S!Wzr!pSO0T~)o68=@Ijm2 z>H)3EA)j|Agd`$5Ddjw0H>IJ(5&h~T9k;^fkuCT=CmD4~fL%(_ge>Re<0L7=>>~xX z4B6-m4F)c44tZ-bcOt9@@aOsyC{5{`Nx*PR6^FQ*j788j)3vPCP%f>89!Fb`dQ&kW zvus^U2j`9?ZQG*Lj+(hP+NQ~cLXL*YC+dn*HP8WJ!`Qxn&^FB7FxJ45!R1vx3sS}A z5&&vdwW74+nzP!sHAk-LPNLljPx00&o75PtovC~O91M?>IKV|sWfUw+DdG09yF>{g zK+h2#SpM^4D%oUA5CE7?{OY1KOUgZ%oItau6zm)2xu-eE$A)oo#AQ)vHR7HLc^Tw2 z+$vr{dlS*Mz1O$TEhq#YXys~Y7q2*NbBv2Wkk} zOEZm^FM@-DE|#cco|*DB8F4#rZYB1HH1ubSqHP&6zIKgkVJ)Ff+F{orqZxV?A}g}p zmmv#&NGWewXEP}VTQ9@oN_}EG>#+c)h>`{RQM1`7#$5H65IlAyhN(EWU$Q0gf-ej@ zoK6`xn4L(FU><73wRCIO3L+%NQAw|^Ud_?d1qO*ltvg=;tWr3O77FQl+_0G|31$Jx zFg~6hd=sV%q~I}j21hz@Zq{jBLxrKeN%ADG7`=;{TIPygOs=vR(gld+iD`Vv zSN*fyRE3L9oqBJtB*o*)SFVc3IOWD!TznlWx|MH!rQi~@OFGXdjrLIF?VIfq1)j{{ zi{i{RJoss}I6d*!8`6z#Uh!`Zb}S|9mspOOPB<=fx^nX22C|^ajP+ffgIb3eN{g%F z`=ou|P%tED*guY3T~&_*9gI;-?mom;Pq#dD#+TC-w>cCXp|Uy< z^|d%Cn+MZp_hSjx78f+%jFaHf9v$W2s-9yZHmR28^kl98l;+eiyDxBXbc@o>ZE-{o zeO�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 Tgcyhz_#+Dx3TrdO20r~i7_9N? literal 0 HcmV?d00001 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg.meta new file mode 100644 index 00000000000..b846aa17545 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ae6c2b051853d83cb9e85a527f516a08 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib.meta new file mode 100644 index 00000000000..0f82551b67a --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f9615e64ff20e6cefb896b5e3502f055 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45.meta new file mode 100644 index 00000000000..5e20f583809 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 385903b30e115d7a58617f6f0fdb6dad +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll new file mode 100644 index 0000000000000000000000000000000000000000..f73a17baa4610612640c7c685e039f9e4ff8b491 GIT binary patch literal 410904 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�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 l-W(tbGcx+_rv@&*JH3;yJ=jDN)*|%Qguw0v599 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

    O^hcQ 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll.meta new file mode 100644 index 00000000000..7dc44b927e4 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4a7b5f56be0f0aa64828fa42c1289fb4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml new file mode 100644 index 00000000000..4d6183a633f --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml @@ -0,0 +1,10465 @@ + + + + Google.Protobuf + + + +

    + Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy + + + + + The threshold above which you should use Buffer.BlockCopy rather than ByteArray.Copy + + + + + Determines which copy routine to use based on the number of bytes to be copied. + + + + + Reverses the order of bytes in the array + + + + + Immutable array of bytes. + + + + + Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. + + + + + Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. + This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical + in .NET Framework. + + + + + Constructs a new ByteString from the given memory. The memory is + *not* copied, and must not be modified after this constructor is called. + + + + + Returns an empty ByteString. + + + + + Returns the length of this ByteString in bytes. + + + + + Returns true if this byte string is empty, false otherwise. + + + + + Provides read-only access to the data of this . + No data is copied so this is the most efficient way of accessing. + + + + + Provides read-only access to the data of this . + No data is copied so this is the most efficient way of accessing. + + + + + Converts this into a byte array. + + The data is copied - changes to the returned array will not be reflected in this ByteString. + A byte array with the same data as this ByteString. + + + + Converts this into a standard base64 representation. + + A base64 representation of this ByteString. + + + + Constructs a from the Base64 Encoded String. + + + + + Constructs a from data in the given stream, synchronously. + + If successful, will be read completely, from the position + at the start of the call. + The stream to copy into a ByteString. + A ByteString with content read from the given stream. + + + + Constructs a from data in the given stream, asynchronously. + + If successful, will be read completely, from the position + at the start of the call. + The stream to copy into a ByteString. + The cancellation token to use when reading from the stream, if any. + A ByteString with content read from the given stream. + + + + Constructs a from the given array. The contents + are copied, so further modifications to the array will not + be reflected in the returned ByteString. + This method can also be invoked in ByteString.CopyFrom(0xaa, 0xbb, ...) form + which is primarily useful for testing. + + + + + Constructs a from a portion of a byte array. + + + + + Constructs a from a read only span. The contents + are copied, so further modifications to the span will not + be reflected in the returned . + + + + + Creates a new by encoding the specified text with + the given encoding. + + + + + Creates a new by encoding the specified text in UTF-8. + + + + + Returns the byte at the given index. + + + + + Converts this into a string by applying the given encoding. + + + This method should only be used to convert binary data which was the result of encoding + text with the given encoding. + + The encoding to use to decode the binary data into text. + The result of decoding the binary data with the given decoding. + + + + Converts this into a string by applying the UTF-8 encoding. + + + This method should only be used to convert binary data which was the result of encoding + text with UTF-8. + + The result of decoding the binary data with the given decoding. + + + + Returns an iterator over the bytes in this . + + An iterator over the bytes in this object. + + + + Returns an iterator over the bytes in this . + + An iterator over the bytes in this object. + + + + Creates a CodedInputStream from this ByteString's data. + + + + + Compares two byte strings for equality. + + The first byte string to compare. + The second byte string to compare. + true if the byte strings are equal; false otherwise. + + + + Compares two byte strings for inequality. + + The first byte string to compare. + The second byte string to compare. + false if the byte strings are equal; true otherwise. + + + + Compares this byte string with another object. + + The object to compare this with. + true if refers to an equal ; false otherwise. + + + + Returns a hash code for this object. Two equal byte strings + will return the same hash code. + + A hash code for this object. + + + + Compares this byte string with another. + + The to compare this with. + true if refers to an equal byte string; false otherwise. + + + + Copies the entire byte array to the destination array provided at the offset specified. + + + + + Writes the entire byte array to the provided stream + + + + + SecuritySafeCritical attribute can not be placed on types with async methods. + This class has ByteString's async methods so it can be marked with SecuritySafeCritical. + + + + + Reads and decodes protocol message fields. + + + + This class is generally used by generated code to read appropriate + primitives from the stream. It effectively encapsulates the lowest + levels of protocol buffer format. + + + Repeated fields and map fields are not handled by this class; use + and to serialize such fields. + + + + + + Whether to leave the underlying stream open when disposing of this stream. + This is always true when there's no stream. + + + + + Buffer of data read from the stream or provided at construction time. + + + + + The stream to read further input from, or null if the byte array buffer was provided + directly on construction, with no further data available. + + + + + The parser state is kept separately so that other parse implementations can reuse the same + parsing primitives. + + + + + Creates a new CodedInputStream reading data from the given byte array. + + + + + Creates a new that reads from the given byte array slice. + + + + + Creates a new reading data from the given stream, which will be disposed + when the returned object is disposed. + + The stream to read from. + + + + Creates a new reading data from the given stream. + + The stream to read from. + true to leave open when the returned + is disposed; false to dispose of the given stream when the + returned object is disposed. + + + + Creates a new CodedInputStream reading data from the given + stream and buffer, using the default limits. + + + + + Creates a new CodedInputStream reading data from the given + stream and buffer, using the specified limits. + + + This chains to the version with the default limits instead of vice versa to avoid + having to check that the default values are valid every time. + + + + + Creates a with the specified size and recursion limits, reading + from an input stream. + + + This method exists separately from the constructor to reduce the number of constructor overloads. + It is likely to be used considerably less frequently than the constructors, as the default limits + are suitable for most use cases. + + The input stream to read from + The total limit of data to read from the stream. + The maximum recursion depth to allow while reading. + A CodedInputStream reading from with the specified size + and recursion limits. + + + + Returns the current position in the input stream, or the position in the input buffer + + + + + Returns the last tag read, or 0 if no tags have been read or we've read beyond + the end of the stream. + + + + + Returns the size limit for this stream. + + + This limit is applied when reading from the underlying stream, as a sanity check. It is + not applied when reading from a byte array data source without an underlying stream. + The default value is Int32.MaxValue. + + + The size limit. + + + + + Returns the recursion limit for this stream. This limit is applied whilst reading messages, + to avoid maliciously-recursive data. + + + The default limit is 100. + + + The recursion limit for this stream. + + + + + Internal-only property; when set to true, unknown fields will be discarded while parsing. + + + + + Internal-only property; provides extension identifiers to compatible messages while parsing. + + + + + Disposes of this instance, potentially closing any underlying stream. + + + As there is no flushing to perform here, disposing of a which + was constructed with the leaveOpen option parameter set to true (or one which + was constructed to read from a byte array) has no effect. + + + + + Verifies that the last call to ReadTag() returned tag 0 - in other words, + we've reached the end of the stream when we expected to. + + The + tag read was not the one specified + + + + Peeks at the next field tag. This is like calling , but the + tag is not consumed. (So a subsequent call to will return the + same value.) + + + + + Reads a field tag, returning the tag of 0 for "end of stream". + + + If this method returns 0, it doesn't necessarily mean the end of all + the data in this CodedInputStream; it may be the end of the logical stream + for an embedded message, for example. + + The next field tag, or 0 for end of stream. (0 is never a valid tag.) + + + + Skips the data for the field with the tag we've just read. + This should be called directly after , when + the caller wishes to skip an unknown field. + + + This method throws if the last-read tag was an end-group tag. + If a caller wishes to skip a group, they should skip the whole group, by calling this method after reading the + start-group tag. This behavior allows callers to call this method on any field they don't understand, correctly + resulting in an error if an end-group tag has not been paired with an earlier start-group tag. + + The last tag was an end-group tag + The last read operation read to the end of the logical stream + + + + Skip a group. + + + + + Reads a double field from the stream. + + + + + Reads a float field from the stream. + + + + + Reads a uint64 field from the stream. + + + + + Reads an int64 field from the stream. + + + + + Reads an int32 field from the stream. + + + + + Reads a fixed64 field from the stream. + + + + + Reads a fixed32 field from the stream. + + + + + Reads a bool field from the stream. + + + + + Reads a string field from the stream. + + + + + Reads an embedded message field value from the stream. + + + + + Reads an embedded group field from the stream. + + + + + Reads a bytes field value from the stream. + + + + + Reads a uint32 field value from the stream. + + + + + Reads an enum field value from the stream. + + + + + Reads an sfixed32 field value from the stream. + + + + + Reads an sfixed64 field value from the stream. + + + + + Reads an sint32 field value from the stream. + + + + + Reads an sint64 field value from the stream. + + + + + Reads a length for length-delimited data. + + + This is internally just reading a varint, but this method exists + to make the calling code clearer. + + + + + Peeks at the next tag in the stream. If it matches , + the tag is consumed and the method returns true; otherwise, the + stream is left in the original position and the method returns false. + + + + + Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits. + This method is optimised for the case where we've got lots of data in the buffer. + That means we can check the size just once, then just read directly from the buffer + without constant rechecking of the buffer length. + + + + + Reads a varint from the input one byte at a time, so that it does not + read any bytes after the end of the varint. If you simply wrapped the + stream in a CodedInputStream and used ReadRawVarint32(Stream) + then you would probably end up reading past the end of the varint since + CodedInputStream buffers its input. + + + + + + + Reads a raw varint from the stream. + + + + + Reads a 32-bit little-endian integer from the stream. + + + + + Reads a 64-bit little-endian integer from the stream. + + + + + Sets currentLimit to (current position) + byteLimit. This is called + when descending into a length-delimited embedded message. The previous + limit is returned. + + The old limit. + + + + Discards the current limit, returning the previous limit. + + + + + Returns whether or not all the data before the limit has been read. + + + + + + Returns true if the stream has reached the end of the input. This is the + case if either the end of the underlying input source has been reached or + the stream has reached a limit created using PushLimit. + + + + + Called when buffer is empty to read more bytes from the + input. If is true, RefillBuffer() guarantees that + either there will be at least one byte in the buffer when it returns + or it will throw an exception. If is false, + RefillBuffer() returns false if no more bytes were available. + + + + + + + Reads a fixed size of bytes from the input. + + + the end of the stream or the current limit was reached + + + + + Reads a top-level message or a nested message after the limits for this message have been pushed. + (parser will proceed until the end of the current limit) + NOTE: this method needs to be public because it's invoked by the generated code - e.g. msg.MergeFrom(CodedInputStream input) method + + + + + Encodes and writes protocol message fields. + + + + This class is generally used by generated code to write appropriate + primitives to the stream. It effectively encapsulates the lowest + levels of protocol buffer format. Unlike some other implementations, + this does not include combined "write tag and value" methods. Generated + code knows the exact byte representations of the tags they're going to write, + so there's no need to re-encode them each time. Manually-written code calling + this class should just call one of the WriteTag overloads before each value. + + + Repeated fields and map fields are not handled by this class; use RepeatedField<T> + and MapField<TKey, TValue> to serialize such fields. + + + + + + Computes the number of bytes that would be needed to encode a + double field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + float field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + uint64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + int64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + int32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + fixed64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + fixed32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + bool field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + string field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + group field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + embedded message field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + bytes field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + uint32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a + enum field, including the tag. The caller is responsible for + converting the enum value to its numeric value. + + + + + Computes the number of bytes that would be needed to encode an + sfixed32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + sfixed64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + sint32 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode an + sint64 field, including the tag. + + + + + Computes the number of bytes that would be needed to encode a length, + as written by . + + + + + Computes the number of bytes that would be needed to encode a varint. + + + + + Computes the number of bytes that would be needed to encode a varint. + + + + + Computes the number of bytes that would be needed to encode a tag. + + + + + The buffer size used by CreateInstance(Stream). + + + + + Creates a new CodedOutputStream that writes directly to the given + byte array. If more bytes are written than fit in the array, + OutOfSpaceException will be thrown. + + + + + Creates a new CodedOutputStream that writes directly to the given + byte array slice. If more bytes are written than fit in the array, + OutOfSpaceException will be thrown. + + + + + Creates a new which write to the given stream, and disposes of that + stream when the returned CodedOutputStream is disposed. + + The stream to write to. It will be disposed when the returned CodedOutputStream is disposed. + + + + Creates a new CodedOutputStream which write to the given stream and uses + the specified buffer size. + + The stream to write to. It will be disposed when the returned CodedOutputStream is disposed. + The size of buffer to use internally. + + + + Creates a new CodedOutputStream which write to the given stream. + + The stream to write to. + If true, is left open when the returned CodedOutputStream is disposed; + if false, the provided stream is disposed as well. + + + + Creates a new CodedOutputStream which write to the given stream and uses + the specified buffer size. + + The stream to write to. + The size of buffer to use internally. + If true, is left open when the returned CodedOutputStream is disposed; + if false, the provided stream is disposed as well. + + + + Returns the current position in the stream, or the position in the output buffer + + + + + Writes a double field value, without a tag, to the stream. + + The value to write + + + + Writes a float field value, without a tag, to the stream. + + The value to write + + + + Writes a uint64 field value, without a tag, to the stream. + + The value to write + + + + Writes an int64 field value, without a tag, to the stream. + + The value to write + + + + Writes an int32 field value, without a tag, to the stream. + + The value to write + + + + Writes a fixed64 field value, without a tag, to the stream. + + The value to write + + + + Writes a fixed32 field value, without a tag, to the stream. + + The value to write + + + + Writes a bool field value, without a tag, to the stream. + + The value to write + + + + Writes a string field value, without a tag, to the stream. + The data is length-prefixed. + + The value to write + + + + Writes a message, without a tag, to the stream. + The data is length-prefixed. + + The value to write + + + + Writes a message, without a tag, to the stream. + Only the message data is written, without a length-delimiter. + + The value to write + + + + Writes a group, without a tag, to the stream. + + The value to write + + + + Write a byte string, without a tag, to the stream. + The data is length-prefixed. + + The value to write + + + + Writes a uint32 value, without a tag, to the stream. + + The value to write + + + + Writes an enum value, without a tag, to the stream. + + The value to write + + + + Writes an sfixed32 value, without a tag, to the stream. + + The value to write. + + + + Writes an sfixed64 value, without a tag, to the stream. + + The value to write + + + + Writes an sint32 value, without a tag, to the stream. + + The value to write + + + + Writes an sint64 value, without a tag, to the stream. + + The value to write + + + + Writes a length (in bytes) for length-delimited data. + + + This method simply writes a rawint, but exists for clarity in calling code. + + Length value, in bytes. + + + + Encodes and writes a tag. + + The number of the field to write the tag for + The wire format type of the tag to write + + + + Writes an already-encoded tag. + + The encoded tag + + + + Writes the given single-byte tag directly to the stream. + + The encoded tag + + + + Writes the given two-byte tag directly to the stream. + + The first byte of the encoded tag + The second byte of the encoded tag + + + + Writes the given three-byte tag directly to the stream. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + + + + Writes the given four-byte tag directly to the stream. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + The fourth byte of the encoded tag + + + + Writes the given five-byte tag directly to the stream. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + The fourth byte of the encoded tag + The fifth byte of the encoded tag + + + + Writes a 32 bit value as a varint. The fast route is taken when + there's enough buffer space left to whizz through without checking + for each byte; otherwise, we resort to calling WriteRawByte each time. + + + + + Writes out an array of bytes. + + + + + Writes out part of an array of bytes. + + + + + Indicates that a CodedOutputStream wrapping a flat byte array + ran out of space. + + + + + Flushes any buffered data and optionally closes the underlying stream, if any. + + + + By default, any underlying stream is closed by this method. To configure this behaviour, + use a constructor overload with a leaveOpen parameter. If this instance does not + have an underlying stream, this method does nothing. + + + For the sake of efficiency, calling this method does not prevent future write calls - but + if a later write ends up writing to a stream which has been disposed, that is likely to + fail. It is recommend that you not call any other methods after this. + + + + + + Flushes any buffered data to the underlying stream (if there is one). + + + + + Verifies that SpaceLeft returns zero. It's common to create a byte array + that is exactly big enough to hold a message, then write to it with + a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that + the message was actually as big as expected, which can help finding bugs. + + + + + If writing to a flat array, returns the space left in the array. Otherwise, + throws an InvalidOperationException. + + + + + Utility to compare if two Lists are the same, and the hash code + of a List. + + + + + Checks if two lists are equal. + + + + + Gets the list's hash code. + + + + + Representation of a map field in a Protocol Buffer message. + + Key type in the map. Must be a type supported by Protocol Buffer map keys. + Value type in the map. Must be a type supported by Protocol Buffers. + + + For string keys, the equality comparison is provided by . + + + Null values are not permitted in the map, either for wrapper types or regular messages. + If a map is deserialized from a data stream and the value is missing from an entry, a default value + is created instead. For primitive types, that is the regular default value (0, the empty string and so + on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length + encoded value for the field. + + + This implementation does not generally prohibit the use of key/value types which are not + supported by Protocol Buffers (e.g. using a key type of byte) but nor does it guarantee + that all operations will work in such cases. + + + The order in which entries are returned when iterating over this object is undefined, and may change + in future versions. + + + + + + Creates a deep clone of this object. + + + A deep clone of this object. + + + + + Adds the specified key/value pair to the map. + + + This operation fails if the key already exists in the map. To replace an existing entry, use the indexer. + + The key to add + The value to add. + The given key already exists in map. + + + + Determines whether the specified key is present in the map. + + The key to check. + true if the map contains the given key; false otherwise. + + + + Removes the entry identified by the given key from the map. + + The key indicating the entry to remove from the map. + true if the map contained the given key before the entry was removed; false otherwise. + + + + Gets the value associated with the specified key. + + The key whose value to get. + When this method returns, the value associated with the specified key, if the key is found; + otherwise, the default value for the type of the parameter. + This parameter is passed uninitialized. + true if the map contains an element with the specified key; otherwise, false. + + + + Gets or sets the value associated with the specified key. + + The key of the value to get or set. + The property is retrieved and key does not exist in the collection. + The value associated with the specified key. If the specified key is not found, + a get operation throws a , and a set operation creates a new element with the specified key. + + + + Gets a collection containing the keys in the map. + + + + + Gets a collection containing the values in the map. + + + + + Adds the specified entries to the map. The keys and values are not automatically cloned. + + The entries to add to the map. + + + + Returns an enumerator that iterates through the collection. + + + An enumerator that can be used to iterate through the collection. + + + + + Returns an enumerator that iterates through a collection. + + + An object that can be used to iterate through the collection. + + + + + Adds the specified item to the map. + + The item to add to the map. + + + + Removes all items from the map. + + + + + Determines whether map contains an entry equivalent to the given key/value pair. + + The key/value pair to find. + + + + + Copies the key/value pairs in this map to an array. + + The array to copy the entries into. + The index of the array at which to start copying values. + + + + Removes the specified key/value pair from the map. + + Both the key and the value must be found for the entry to be removed. + The key/value pair to remove. + true if the key/value pair was found and removed; false otherwise. + + + + Gets the number of elements contained in the map. + + + + + Gets a value indicating whether the map is read-only. + + + + + Determines whether the specified , is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Compares this map with another for equality. + + + The order of the key/value pairs in the maps is not deemed significant in this comparison. + + The map to compare this with. + true if refers to an equal map; false otherwise. + + + + Adds entries to the map from the given stream. + + + It is assumed that the stream is initially positioned after the tag specified by the codec. + This method will continue reading entries from the stream until the end is reached, or + a different tag is encountered. + + Stream to read from + Codec describing how the key/value pairs are encoded + + + + Adds entries to the map from the given parse context. + + + It is assumed that the input is initially positioned after the tag specified by the codec. + This method will continue reading entries from the input until the end is reached, or + a different tag is encountered. + + Input to read from + Codec describing how the key/value pairs are encoded + + + + Writes the contents of this map to the given coded output stream, using the specified codec + to encode each entry. + + The output stream to write to. + The codec to use for each entry. + + + + Writes the contents of this map to the given write context, using the specified codec + to encode each entry. + + The write context to write to. + The codec to use for each entry. + + + + Calculates the size of this map based on the given entry codec. + + The codec to use to encode each entry. + + + + + Returns a string representation of this repeated field, in the same + way as it would be represented by the default JSON formatter. + + + + + A codec for a specific map field. This contains all the information required to encode and + decode the nested messages. + + + + + Creates a new entry codec based on a separate key codec and value codec, + and the tag to use for each map entry. + + The key codec. + The value codec. + The map tag to use to introduce each map entry. + + + + The key codec. + + + + + The value codec. + + + + + The tag used in the enclosing message to indicate map entries. + + + + + Provides a central place to implement equality comparisons, primarily for bitwise float/double equality. + + + + + Returns an equality comparer for suitable for Protobuf equality comparisons. + This is usually just the default equality comparer for the type, but floating point numbers are compared + bitwise. + + The type of equality comparer to return. + The equality comparer. + + + + Returns an equality comparer suitable for comparing 64-bit floating point values, by bitwise comparison. + (NaN values are considered equal, but only when they have the same representation.) + + + + + Returns an equality comparer suitable for comparing 32-bit floating point values, by bitwise comparison. + (NaN values are considered equal, but only when they have the same representation.) + + + + + Returns an equality comparer suitable for comparing nullable 64-bit floating point values, by bitwise comparison. + (NaN values are considered equal, but only when they have the same representation.) + + + + + Returns an equality comparer suitable for comparing nullable 32-bit floating point values, by bitwise comparison. + (NaN values are considered equal, but only when they have the same representation.) + + + + + Read-only wrapper around another dictionary. + + + + + The contents of a repeated field: essentially, a collection with some extra + restrictions (no null values) and capabilities (deep cloning). + + + This implementation does not generally prohibit the use of types which are not + supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases. + + The element type of the repeated field. + + + + Creates a deep clone of this repeated field. + + + If the field type is + a message type, each element is also cloned; otherwise, it is + assumed that the field type is primitive (including string and + bytes, both of which are immutable) and so a simple copy is + equivalent to a deep clone. + + A deep clone of this repeated field. + + + + Adds the entries from the given input stream, decoding them with the specified codec. + + The input stream to read from. + The codec to use in order to read each entry. + + + + Adds the entries from the given parse context, decoding them with the specified codec. + + The input to read from. + The codec to use in order to read each entry. + + + + Calculates the size of this collection based on the given codec. + + The codec to use when encoding each field. + The number of bytes that would be written to an output by one of the WriteTo methods, + using the same codec. + + + + Writes the contents of this collection to the given , + encoding each value using the specified codec. + + The output stream to write to. + The codec to use when encoding each value. + + + + Writes the contents of this collection to the given write context, + encoding each value using the specified codec. + + The write context to write to. + The codec to use when encoding each value. + + + + Gets and sets the capacity of the RepeatedField's internal array. WHen set, the internal array is reallocated to the given capacity. + The new value is less than Count -or- when Count is less than 0. + + + + + Adds the specified item to the collection. + + The item to add. + + + + Removes all items from the collection. + + + + + Determines whether this collection contains the given item. + + The item to find. + true if this collection contains the given item; false otherwise. + + + + Copies this collection to the given array. + + The array to copy to. + The first index of the array to copy to. + + + + Removes the specified item from the collection + + The item to remove. + true if the item was found and removed; false otherwise. + + + + Gets the number of elements contained in the collection. + + + + + Gets a value indicating whether the collection is read-only. + + + + + Adds all of the specified values into this collection. + + The values to add to this collection. + + + + Adds all of the specified values into this collection. This method is present to + allow repeated fields to be constructed from queries within collection initializers. + Within non-collection-initializer code, consider using the equivalent + method instead for clarity. + + The values to add to this collection. + + + + Returns an enumerator that iterates through the collection. + + + An enumerator that can be used to iterate through the collection. + + + + + Determines whether the specified , is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns an enumerator that iterates through a collection. + + + An object that can be used to iterate through the collection. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Compares this repeated field with another for equality. + + The repeated field to compare this with. + true if refers to an equal repeated field; false otherwise. + + + + Returns the index of the given item within the collection, or -1 if the item is not + present. + + The item to find in the collection. + The zero-based index of the item, or -1 if it is not found. + + + + Inserts the given item at the specified index. + + The index at which to insert the item. + The item to insert. + + + + Removes the item at the given index. + + The zero-based index of the item to remove. + + + + Returns a string representation of this repeated field, in the same + way as it would be represented by the default JSON formatter. + + + + + Gets or sets the item at the specified index. + + + The element at the specified index. + + The zero-based index of the element to get or set. + The item at the specified index. + + + + Extension methods for , effectively providing + the familiar members from previous desktop framework versions while + targeting the newer releases, .NET Core etc. + + + + + Returns the public getter of a property, or null if there is no such getter + (either because it's read-only, or the getter isn't public). + + + + + Returns the public setter of a property, or null if there is no such setter + (either because it's write-only, or the setter isn't public). + + + + + Provides extension methods on Type that just proxy to TypeInfo. + These are used to support the new type system from .NET 4.5, without + having calls to GetTypeInfo all over the place. While the methods here are meant to be + broadly compatible with the desktop framework, there are some subtle differences in behaviour - but + they're not expected to affect our use cases. While the class is internal, that should be fine: we can + evaluate each new use appropriately. + + + + + See https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom + + + + + Returns a representation of the public property associated with the given name in the given type, + including inherited properties or null if there is no such public property. + Here, "public property" means a property where either the getter, or the setter, or both, is public. + + + + + Returns a representation of the public method associated with the given name in the given type, + including inherited methods. + + + This has a few differences compared with Type.GetMethod in the desktop framework. It will throw + if there is an ambiguous match even between a private method and a public one, but it *won't* throw + if there are two overloads at different levels in the type hierarchy (e.g. class Base declares public void Foo(int) and + class Child : Base declares public void Foo(long)). + + One type in the hierarchy declared more than one method with the same name + + + + Represents a non-generic extension definition. This API is experimental and subject to change. + + + + + Internal use. Creates a new extension with the specified field number. + + + + + Gets the field number of this extension + + + + + Represents a type-safe extension identifier used for getting and setting single extension values in instances. + This API is experimental and subject to change. + + The message type this field applies to + The field value type of this extension + + + + Creates a new extension identifier with the specified field number and codec + + + + + Represents a type-safe extension identifier used for getting repeated extension values in instances. + This API is experimental and subject to change. + + The message type this field applies to + The repeated field value type of this extension + + + + Creates a new repeated extension identifier with the specified field number and codec + + + + + Provides extensions to messages while parsing. This API is experimental and subject to change. + + + + + Creates a new empty extension registry + + + + + Gets the total number of extensions in this extension registry + + + + + Returns whether the registry is readonly + + + + + Adds the specified extension to the registry + + + + + Adds the specified extensions to the registry + + + + + Clears the registry of all values + + + + + Gets whether the extension registry contains the specified extension + + + + + Copies the arrays in the registry set to the specified array at the specified index + + The array to copy to + The array index to start at + + + + Returns an enumerator to enumerate through the items in the registry + + Returns an enumerator for the extensions in this registry + + + + Removes the specified extension from the set + + The extension + true if the extension was removed, otherwise false + + + + Clones the registry into a new registry + + + + + Methods for managing s with null checking. + + Most users will not use this class directly and its API is experimental and subject to change. + + + + + Gets the value of the specified extension + + + + + Gets the value of the specified repeated extension or null if it doesn't exist in this set + + + + + Gets the value of the specified repeated extension, registering it if it doesn't exist + + + + + Sets the value of the specified extension. This will make a new instance of ExtensionSet if the set is null. + + + + + Gets whether the value of the specified extension is set + + + + + Clears the value of the specified extension + + + + + Clears the value of the specified extension + + + + + Tries to merge a field from the coded input, returning true if the field was merged. + If the set is null or the field was not otherwise merged, this returns false. + + + + + Tries to merge a field from the coded input, returning true if the field was merged. + If the set is null or the field was not otherwise merged, this returns false. + + + + + Merges the second set into the first set, creating a new instance if first is null + + + + + Clones the set into a new set. If the set is null, this returns null + + + + + Used for keeping track of extensions in messages. + methods route to this set. + + Most users will not need to use this class directly + + The message type that extensions in this set target + + + + Gets a hash code of the set + + + + + Returns whether this set is equal to the other object + + + + + Calculates the size of this extension set + + + + + Writes the extension values in this set to the output stream + + + + + Writes the extension values in this set to the write context + + + + + Factory methods for . + + + + + Retrieves a codec suitable for a string field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a bytes field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a bool field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an int32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an sint32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a fixed32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an sfixed32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a uint32 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an int64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an sint64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a fixed64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an sfixed64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a uint64 field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a float field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for a double field with the given tag. + + The tag. + A codec for the given tag. + + + + Retrieves a codec suitable for an enum field with the given tag. + + The tag. + A conversion function from to the enum type. + A conversion function from the enum type to . + A codec for the given tag. + + + + Retrieves a codec suitable for a string field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a bytes field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a bool field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an int32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an sint32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a fixed32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an sfixed32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a uint32 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an int64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an sint64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a fixed64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an sfixed64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a uint64 field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a float field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a double field with the given tag. + + The tag. + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for an enum field with the given tag. + + The tag. + A conversion function from to the enum type. + A conversion function from the enum type to . + The default value. + A codec for the given tag. + + + + Retrieves a codec suitable for a message field with the given tag. + + The tag. + A parser to use for the message type. + A codec for the given tag. + + + + Retrieves a codec suitable for a group field with the given tag. + + The start group tag. + The end group tag. + A parser to use for the group message type. + A codec for given tag + + + + Creates a codec for a wrapper type of a class - which must be string or ByteString. + + + + + Creates a codec for a wrapper type of a struct - which must be Int32, Int64, UInt32, UInt64, + Bool, Single or Double. + + + + + Helper code to create codecs for wrapper types. + + + Somewhat ugly with all the static methods, but the conversions involved to/from nullable types make it + slightly tricky to improve. So long as we keep the public API (ForClassWrapper, ForStructWrapper) in place, + we can refactor later if we come up with something cleaner. + + + + + Returns a field codec which effectively wraps a value of type T in a message. + + + + + + + An encode/decode pair for a single field. This effectively encapsulates + all the information needed to read or write the field value from/to a coded + stream. + + + This class is public and has to be as it is used by generated code, but its public + API is very limited - just what the generated code needs to call directly. + + + + This never writes default values to the stream, and does not address "packedness" + in repeated fields itself, other than to know whether or not the field *should* be packed. + + + + + Merges an input stream into a value + + + + + Merges a value into a reference to another value, returning a boolean if the value was set + + + + + Returns a delegate to write a value (unconditionally) to a coded output stream. + + + + + Returns the size calculator for just a value. + + + + + Returns a delegate to read a value from a coded input stream. It is assumed that + the stream is already positioned on the appropriate tag. + + + + + Returns a delegate to merge a value from a coded input stream. + It is assumed that the stream is already positioned on the appropriate tag + + + + + Returns a delegate to merge two values together. + + + + + Returns the fixed size for an entry, or 0 if sizes vary. + + + + + Gets the tag of the codec. + + + The tag of the codec. + + + + + Gets the end tag of the codec or 0 if there is no end tag + + + The end tag of the codec. + + + + + Default value for this codec. Usually the same for every instance of the same type, but + for string/ByteString wrapper fields the codec's default value is null, whereas for + other string/ByteString fields it's "" or ByteString.Empty. + + + The default value of the codec's type. + + + + + Write a tag and the given value, *if* the value is not the default. + + + + + Write a tag and the given value, *if* the value is not the default. + + + + + Reads a value of the codec type from the given . + + The input stream to read from. + The value read from the stream. + + + + Reads a value of the codec type from the given . + + The parse context to read from. + The value read. + + + + Calculates the size required to write the given value, with a tag, + if the value is not the default. + + + + + Calculates the size required to write the given value, with a tag, even + if the value is the default. + + + + + A tree representation of a FieldMask. Each leaf node in this tree represent + a field path in the FieldMask. + + For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be: + + [root] -+- foo -+- bar + | | + | +- baz + | + +- bar --- baz + + + By representing FieldMasks with this tree structure we can easily convert + a FieldMask to a canonical form, merge two FieldMasks, calculate the + intersection to two FieldMasks and traverse all fields specified by the + FieldMask in a message tree. + + + + + Creates an empty FieldMaskTree. + + + + + Creates a FieldMaskTree for a given FieldMask. + + + + + Adds a field path to the tree. In a FieldMask, every field path matches the + specified field as well as all its sub-fields. For example, a field path + "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding + a field path to the tree, redundant sub-paths will be removed. That is, + after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it + exists, which will turn the tree node for "foo.bar" to a leaf node. + Likewise, if the field path to add is a sub-path of an existing leaf node, + nothing will be changed in the tree. + + + + + Merges all field paths in a FieldMask into this tree. + + + + + Converts this tree to a FieldMask. + + + + + Gathers all field paths in a sub-tree. + + + + + Adds the intersection of this tree with the given to . + + + + + Merges all fields specified by this FieldMaskTree from to . + + + + + Merges all fields specified by a sub-tree from to . + + + + + Class containing helpful workarounds for various platform compatibility + + + + + Interface for a Protocol Buffers message, supporting + parsing from and writing to . + + + + + Internal implementation of merging data from given parse context into this message. + Users should never invoke this method directly. + + + + + Internal implementation of writing this message to a given write context. + Users should never invoke this method directly. + + + + + A message type that has a custom string format for diagnostic purposes. + + + + Calling on a generated message type normally + returns the JSON representation. If a message type implements this interface, + then the method will be called instead of the regular + JSON formatting code, but only when ToString() is called either on the message itself + or on another message which contains it. This does not affect the normal JSON formatting of + the message. + + + For example, if you create a proto message representing a GUID, the internal + representation may be a bytes field or four fixed32 fields. However, when debugging + it may be more convenient to see a result in the same format as provides. + + This interface extends to avoid it accidentally being implemented + on types other than messages, where it would not be used by anything in the framework. + + + + + Returns a string representation of this object, for diagnostic purposes. + + + This method is called when a message is formatted as part of a + call. It does not affect the JSON representation used by other than + in calls to . While it is recommended + that the result is valid JSON, this is never assumed by the Protobuf library. + + A string representation of this object, for diagnostic purposes. + + + + Generic interface for a deeply cloneable type. + + + + All generated messages implement this interface, but so do some non-message types. + Additionally, due to the type constraint on T in , + it is simpler to keep this as a separate interface. + + + The type itself, returned by the method. + + + + Creates a deep clone of this object. + + A deep clone of this object. + + + + Generic interface for a Protocol Buffers message containing one or more extensions, where the type parameter is expected to be the same type as the implementation class. + This interface is experiemental and is subject to change. + + + + + Gets the value of the specified extension + + + + + Gets the value of the specified repeated extension or null if the extension isn't registered in this set. + For a version of this method that never returns null, use + + + + + Gets the value of the specified repeated extension, registering it if it hasn't already been registered. + + + + + Sets the value of the specified extension + + + + + Gets whether the value of the specified extension is set + + + + + Clears the value of the specified extension + + + + + Clears the value of the specified repeated extension + + + + + Interface for a Protocol Buffers message, supporting + basic operations required for serialization. + + + + + Merges the data from the specified coded input stream with the current message. + + See the user guide for precise merge semantics. + + + + + Writes the data to the given coded output stream. + + Coded output stream to write the data to. Must not be null. + + + + Calculates the size of this message in Protocol Buffer wire format, in bytes. + + The number of bytes required to write this message + to a coded output stream. + + + + Descriptor for this message. All instances are expected to return the same descriptor, + and for generated types this will be an explicitly-implemented member, returning the + same value as the static property declared on the type. + + + + + Generic interface for a Protocol Buffers message, + where the type parameter is expected to be the same type as + the implementation class. + + The message type. + + + + Merges the given message into this one. + + See the user guide for precise merge semantics. + The message to merge with this one. Must not be null. + + + + Thrown when an attempt is made to parse invalid JSON, e.g. using + a non-string property key, or including a redundant comma. Parsing a protocol buffer + message represented in JSON using can throw both this + exception and depending on the situation. This + exception is only thrown for "pure JSON" errors, whereas InvalidProtocolBufferException + is thrown when the JSON may be valid in and of itself, but cannot be parsed as a protocol buffer + message. + + + + + Thrown when a protocol message being parsed is invalid in some way, + e.g. it contains a malformed varint or a negative byte length. + + + + + Creates an exception for an error condition of an invalid tag being encountered. + + + + + Reflection-based converter from messages to JSON. + + + + Instances of this class are thread-safe, with no mutable state. + + + This is a simple start to get JSON formatting working. As it's reflection-based, + it's not as quick as baking calls into generated messages - but is a simpler implementation. + (This code is generally not heavily optimized.) + + + + + + Returns a formatter using the default settings. + + + + + The JSON representation of the first 160 characters of Unicode. + Empty strings are replaced by the static constructor. + + + + + Creates a new formatted with the given settings. + + The settings. + + + + Formats the specified message as JSON. + + The message to format. + The formatted message. + + + + Formats the specified message as JSON. + + The message to format. + The TextWriter to write the formatted message to. + The formatted message. + + + + Converts a message to JSON for diagnostic purposes with no extra context. + + + + This differs from calling on the default JSON + formatter in its handling of . As no type registry is available + in calls, the normal way of resolving the type of + an Any message cannot be applied. Instead, a JSON property named @value + is included with the base64 data from the property of the message. + + The value returned by this method is only designed to be used for diagnostic + purposes. It may not be parsable by , and may not be parsable + by other Protocol Buffer implementations. + + The message to format for diagnostic purposes. + The diagnostic-only JSON representation of the message + + + + Determines whether or not a field value should be serialized according to the field, + its value in the message, and the settings of this formatter. + + + + + Writes a single value to the given writer as JSON. Only types understood by + Protocol Buffers can be written in this way. This method is only exposed for + advanced use cases; most users should be using + or . + + The writer to write the value to. Must not be null. + The value to write. May be null. + + + + Central interception point for well-known type formatting. Any well-known types which + don't need special handling can fall back to WriteMessage. We avoid assuming that the + values are using the embedded well-known types, in order to allow for dynamic messages + in the future. + + + + + Writes a string (including leading and trailing double quotes) to a builder, escaping as required. + + + Other than surrogate pair handling, this code is mostly taken from src/google/protobuf/util/internal/json_escaping.cc. + + + + + Settings controlling JSON formatting. + + + + + Default settings, as used by + + + + + Whether fields which would otherwise not be included in the formatted data + should be formatted even when the value is not present, or has the default value. + This option only affects fields which don't support "presence" (e.g. + singular non-optional proto3 primitive fields). + + + + + The type registry used to format messages. + + + + + Whether to format enums as ints. Defaults to false. + + + + + Whether to use the original proto field names as defined in the .proto file. Defaults to false. + + + + + Creates a new object with the specified formatting of default values + and an empty type registry. + + true if default values (0, empty strings etc) should be formatted; false otherwise. + + + + Creates a new object with the specified formatting of default values + and type registry. + + true if default values (0, empty strings etc) should be formatted; false otherwise. + The to use when formatting messages. + + + + Creates a new object with the specified parameters. + + true if default values (0, empty strings etc) should be formatted; false otherwise. + The to use when formatting messages. TypeRegistry.Empty will be used if it is null. + true to format the enums as integers; false to format enums as enum names. + true to preserve proto field names; false to convert them to lowerCamelCase. + + + + Creates a new object with the specified formatting of default values and the current settings. + + true if default values (0, empty strings etc) should be formatted; false otherwise. + + + + Creates a new object with the specified type registry and the current settings. + + The to use when formatting messages. + + + + Creates a new object with the specified enums formatting option and the current settings. + + true to format the enums as integers; false to format enums as enum names. + + + + Creates a new object with the specified field name formatting option and the current settings. + + true to preserve proto field names; false to convert them to lowerCamelCase. + + + + Reflection-based converter from JSON to messages. + + + + Instances of this class are thread-safe, with no mutable state. + + + This is a simple start to get JSON parsing working. As it's reflection-based, + it's not as quick as baking calls into generated messages - but is a simpler implementation. + (This code is generally not heavily optimized.) + + + + + + Returns a formatter using the default settings. + + + + + Creates a new formatted with the given settings. + + The settings. + + + + Parses and merges the information into the given message. + + The message to merge the JSON information into. + The JSON to parse. + + + + Parses JSON read from and merges the information into the given message. + + The message to merge the JSON information into. + Reader providing the JSON to parse. + + + + Merges the given message using data from the given tokenizer. In most cases, the next + token should be a "start object" token, but wrapper types and nullity can invalidate + that assumption. This is implemented as an LL(1) recursive descent parser over the stream + of tokens provided by the tokenizer. This token stream is assumed to be valid JSON, with the + tokenizer performing that validation - but not every token stream is valid "protobuf JSON". + + + + + Parses into a new message. + + The type of message to create. + The JSON to parse. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Parses JSON read from into a new message. + + The type of message to create. + Reader providing the JSON to parse. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Parses into a new message. + + The JSON to parse. + Descriptor of message type to parse. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Parses JSON read from into a new message. + + Reader providing the JSON to parse. + Descriptor of message type to parse. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Creates a new instance of the message type for the given field. + + + + + Checks that any infinite/NaN values originated from the correct text. + This corrects the lenient whitespace handling of double.Parse/float.Parse, as well as the + way that Mono parses out-of-range values as infinity. + + + + + Settings controlling JSON parsing. + + + + + Default settings, as used by . This has the same default + recursion limit as , and an empty type registry. + + + + + The maximum depth of messages to parse. Note that this limit only applies to parsing + messages, not collections - so a message within a collection within a message only counts as + depth 2, not 3. + + + + + The type registry used to parse messages. + + + + + Whether the parser should ignore unknown fields (true) or throw an exception when + they are encountered (false). + + + + + Creates a new object with the specified recursion limit. + + The maximum depth of messages to parse + + + + Creates a new object with the specified recursion limit and type registry. + + The maximum depth of messages to parse + The type registry used to parse messages + + + + Creates a new object set to either ignore unknown fields, or throw an exception + when unknown fields are encountered. + + true if unknown fields should be ignored when parsing; false to throw an exception. + + + + Creates a new object based on this one, but with the specified recursion limit. + + The new recursion limit. + + + + Creates a new object based on this one, but with the specified type registry. + + The new type registry. Must not be null. + + + + Simple but strict JSON tokenizer, rigidly following RFC 7159. + + + + This tokenizer is stateful, and only returns "useful" tokens - names, values etc. + It does not create tokens for the separator between names and values, or for the comma + between values. It validates the token stream as it goes - so callers can assume that the + tokens it produces are appropriate. For example, it would never produce "start object, end array." + + Implementation details: the base class handles single token push-back and + Not thread-safe. + + + + + Creates a tokenizer that reads from the given text reader. + + + + + Creates a tokenizer that first replays the given list of tokens, then continues reading + from another tokenizer. Note that if the returned tokenizer is "pushed back", that does not push back + on the continuation tokenizer, or vice versa. Care should be taken when using this method - it was + created for the sake of Any parsing. + + + + + Returns the depth of the stack, purely in objects (not collections). + Informally, this is the number of remaining unclosed '{' characters we have. + + + + + Returns the next JSON token in the stream. An EndDocument token is returned to indicate the end of the stream, + after which point Next() should not be called again. + + This implementation provides single-token buffering, and calls if there is no buffered token. + The next token in the stream. This is never null. + This method is called after an EndDocument token has been returned + The input text does not comply with RFC 7159 + + + + Returns the next JSON token in the stream, when requested by the base class. (The method delegates + to this if it doesn't have a buffered token.) + + This method is called after an EndDocument token has been returned + The input text does not comply with RFC 7159 + + + + Skips the value we're about to read. This must only be called immediately after reading a property name. + If the value is an object or an array, the complete object/array is skipped. + + + + + Tokenizer which first exhausts a list of tokens, then consults another tokenizer. + + + + + Tokenizer which does all the *real* work of parsing JSON. + + + + + This method essentially just loops through characters skipping whitespace, validating and + changing state (e.g. from ObjectBeforeColon to ObjectAfterColon) + until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point + it returns the token. Although the method is large, it would be relatively hard to break down further... most + of it is the large switch statement, which sometimes returns and sometimes doesn't. + + + + + Reads a string token. It is assumed that the opening " has already been read. + + + + + Reads an escaped character. It is assumed that the leading backslash has already been read. + + + + + Reads an escaped Unicode 4-nybble hex sequence. It is assumed that the leading \u has already been read. + + + + + Consumes a text-only literal, throwing an exception if the read text doesn't match it. + It is assumed that the first letter of the literal has already been read. + + + + + Validates that we're in a valid state to read a value (using the given error prefix if necessary) + and changes the state to the appropriate one, e.g. ObjectAfterColon to ObjectAfterProperty. + + + + + Pops the top-most container, and sets the state to the appropriate one for the end of a value + in the parent container. + + + + + Possible states of the tokenizer. + + + This is a flags enum purely so we can simply and efficiently represent a set of valid states + for checking. + + Each is documented with an example, + where ^ represents the current position within the text stream. The examples all use string values, + but could be any value, including nested objects/arrays. + The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects). + Any additional notional state of "AfterValue" indicates that a value has been completed, at which + point there's an immediate transition to ExpectedEndOfDocument, ObjectAfterProperty or ArrayAfterValue. + + + These states were derived manually by reading RFC 7159 carefully. + + + + + + ^ { "foo": "bar" } + Before the value in a document. Next states: ObjectStart, ArrayStart, "AfterValue" + + + + + { "foo": "bar" } ^ + After the value in a document. Next states: ReaderExhausted + + + + + { "foo": "bar" } ^ (and already read to the end of the reader) + Terminal state. + + + + + { ^ "foo": "bar" } + Before the *first* property in an object. + Next states: + "AfterValue" (empty object) + ObjectBeforeColon (read a name) + + + + + { "foo" ^ : "bar", "x": "y" } + Next state: ObjectAfterColon + + + + + { "foo" : ^ "bar", "x": "y" } + Before any property other than the first in an object. + (Equivalently: after any property in an object) + Next states: + "AfterValue" (value is simple) + ObjectStart (value is object) + ArrayStart (value is array) + + + + + { "foo" : "bar" ^ , "x" : "y" } + At the end of a property, so expecting either a comma or end-of-object + Next states: ObjectAfterComma or "AfterValue" + + + + + { "foo":"bar", ^ "x":"y" } + Read the comma after the previous property, so expecting another property. + This is like ObjectStart, but closing brace isn't valid here + Next state: ObjectBeforeColon. + + + + + [ ^ "foo", "bar" ] + Before the *first* value in an array. + Next states: + "AfterValue" (read a value) + "AfterValue" (end of array; will pop stack) + + + + + [ "foo" ^ , "bar" ] + After any value in an array, so expecting either a comma or end-of-array + Next states: ArrayAfterComma or "AfterValue" + + + + + [ "foo", ^ "bar" ] + After a comma in an array, so there *must* be another value (simple or complex). + Next states: "AfterValue" (simple value), StartObject, StartArray + + + + + Wrapper around a text reader allowing small amounts of buffering and location handling. + + + + + The buffered next character, if we have one. + + + + + Returns the next character in the stream, or null if we have reached the end. + + + + + + Creates a new exception appropriate for the current state of the reader. + + + + + Stream implementation which proxies another stream, only allowing a certain amount + of data to be read. Note that this is only used to read delimited streams, so it + doesn't attempt to implement everything. + + + + + Extension methods on and . + + + + + Merges data from the given byte array into an existing message. + + The message to merge the data into. + The data to merge, which must be protobuf-encoded binary data. + + + + Merges data from the given byte array slice into an existing message. + + The message to merge the data into. + The data containing the slice to merge, which must be protobuf-encoded binary data. + The offset of the slice to merge. + The length of the slice to merge. + + + + Merges data from the given byte string into an existing message. + + The message to merge the data into. + The data to merge, which must be protobuf-encoded binary data. + + + + Merges data from the given stream into an existing message. + + The message to merge the data into. + Stream containing the data to merge, which must be protobuf-encoded binary data. + + + + Merges data from the given span into an existing message. + + The message to merge the data into. + Span containing the data to merge, which must be protobuf-encoded binary data. + + + + Merges length-delimited data from the given stream into an existing message. + + + The stream is expected to contain a length and then the data. Only the amount of data + specified by the length will be consumed. + + The message to merge the data into. + Stream containing the data to merge, which must be protobuf-encoded binary data. + + + + Converts the given message into a byte array in protobuf encoding. + + The message to convert. + The message data as a byte array. + + + + Writes the given message data to the given stream in protobuf encoding. + + The message to write to the stream. + The stream to write to. + + + + Writes the length and then data of the given message to a stream. + + The message to write. + The output stream to write to. + + + + Converts the given message into a byte string in protobuf encoding. + + The message to convert. + The message data as a byte string. + + + + Writes the given message data to the given buffer writer in protobuf encoding. + + The message to write to the stream. + The stream to write to. + + + + Writes the given message data to the given span in protobuf encoding. + The size of the destination span needs to fit the serialized size + of the message exactly, otherwise an exception is thrown. + + The message to write to the stream. + The span to write to. Size must match size of the message exactly. + + + + Checks if all required fields in a message have values set. For proto3 messages, this returns true + + + + + A general message parser, typically used by reflection-based code as all the methods + return simple . + + + + + Creates a template instance ready for population. + + An empty message. + + + + Parses a message from a byte array. + + The byte array containing the message. Must not be null. + The newly parsed message. + + + + Parses a message from a byte array slice. + + The byte array containing the message. Must not be null. + The offset of the slice to parse. + The length of the slice to parse. + The newly parsed message. + + + + Parses a message from the given byte string. + + The data to parse. + The parsed message. + + + + Parses a message from the given stream. + + The stream to parse. + The parsed message. + + + + Parses a message from the given sequence. + + The data to parse. + The parsed message. + + + + Parses a message from the given span. + + The data to parse. + The parsed message. + + + + Parses a length-delimited message from the given stream. + + + The stream is expected to contain a length and then the data. Only the amount of data + specified by the length will be consumed. + + The stream to parse. + The parsed message. + + + + Parses a message from the given coded input stream. + + The stream to parse. + The parsed message. + + + + Parses a message from the given JSON. + + The JSON to parse. + The parsed message. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Creates a new message parser which optionally discards unknown fields when parsing. + + Whether or not to discard unknown fields when parsing. + A newly configured message parser. + + + + Creates a new message parser which registers extensions from the specified registry upon creating the message instance + + The extensions to register + A newly configured message parser. + + + + A parser for a specific message type. + + +

    + This delegates most behavior to the + implementation within the original type, but + provides convenient overloads to parse from a variety of sources. +

    +

    + Most applications will never need to create their own instances of this type; + instead, use the static Parser property of a generated message type to obtain a + parser for that type. +

    +
    + The type of message to be parsed. +
    + + + Creates a new parser. + + + The factory method is effectively an optimization over using a generic constraint + to require a parameterless constructor: delegates are significantly faster to execute. + + Function to invoke when a new, empty message is required. + + + + Creates a template instance ready for population. + + An empty message. + + + + Parses a message from a byte array. + + The byte array containing the message. Must not be null. + The newly parsed message. + + + + Parses a message from a byte array slice. + + The byte array containing the message. Must not be null. + The offset of the slice to parse. + The length of the slice to parse. + The newly parsed message. + + + + Parses a message from the given byte string. + + The data to parse. + The parsed message. + + + + Parses a message from the given stream. + + The stream to parse. + The parsed message. + + + + Parses a message from the given sequence. + + The data to parse. + The parsed message. + + + + Parses a message from the given span. + + The data to parse. + The parsed message. + + + + Parses a length-delimited message from the given stream. + + + The stream is expected to contain a length and then the data. Only the amount of data + specified by the length will be consumed. + + The stream to parse. + The parsed message. + + + + Parses a message from the given coded input stream. + + The stream to parse. + The parsed message. + + + + Parses a message from the given JSON. + + The JSON to parse. + The parsed message. + The JSON does not comply with RFC 7159 + The JSON does not represent a Protocol Buffers message correctly + + + + Creates a new message parser which optionally discards unknown fields when parsing. + + Whether or not to discard unknown fields when parsing. + A newly configured message parser. + + + + Creates a new message parser which registers extensions from the specified registry upon creating the message instance + + The extensions to register + A newly configured message parser. + + + + Struct used to hold the keys for the fieldByNumber table in DescriptorPool and the keys for the + extensionByNumber table in ExtensionRegistry. + + + + + An opaque struct that represents the current parsing state and is passed along + as the parsing proceeds. + All the public methods are intended to be invoked only by the generated code, + users should never invoke them directly. + + + + + Initialize a , building all from defaults and + the given . + + + + + Initialize a using existing , e.g. from . + + + + + Creates a ParseContext instance from CodedInputStream. + WARNING: internally this copies the CodedInputStream's state, so after done with the ParseContext, + the CodedInputStream's state needs to be updated. + + + + + Returns the last tag read, or 0 if no tags have been read or we've read beyond + the end of the input. + + + + + Internal-only property; when set to true, unknown fields will be discarded while parsing. + + + + + Internal-only property; provides extension identifiers to compatible messages while parsing. + + + + + Reads a field tag, returning the tag of 0 for "end of input". + + + If this method returns 0, it doesn't necessarily mean the end of all + the data in this CodedInputReader; it may be the end of the logical input + for an embedded message, for example. + + The next field tag, or 0 for end of input. (0 is never a valid tag.) + + + + Reads a double field from the input. + + + + + Reads a float field from the input. + + + + + Reads a uint64 field from the input. + + + + + Reads an int64 field from the input. + + + + + Reads an int32 field from the input. + + + + + Reads a fixed64 field from the input. + + + + + Reads a fixed32 field from the input. + + + + + Reads a bool field from the input. + + + + + Reads a string field from the input. + + + + + Reads an embedded message field value from the input. + + + + + Reads an embedded group field from the input. + + + + + Reads a bytes field value from the input. + + + + + Reads a uint32 field value from the input. + + + + + Reads an enum field value from the input. + + + + + Reads an sfixed32 field value from the input. + + + + + Reads an sfixed64 field value from the input. + + + + + Reads an sint32 field value from the input. + + + + + Reads an sint64 field value from the input. + + + + + Reads a length for length-delimited data. + + + This is internally just reading a varint, but this method exists + to make the calling code clearer. + + + + + The position within the current buffer (i.e. the next byte to read) + + + + + Size of the current buffer + + + + + If we are currently inside a length-delimited block, this is the number of + bytes in the buffer that are still available once we leave the delimited block. + + + + + The absolute position of the end of the current length-delimited block (including totalBytesRetired) + + + + + The total number of consumed before the start of the current buffer. The + total bytes read up to the current position can be computed as + totalBytesRetired + bufferPos. + + + + + The last tag we read. 0 indicates we've read to the end of the stream + (or haven't read anything yet). + + + + + The next tag, used to store the value read by PeekTag. + + + + + Internal-only property; when set to true, unknown fields will be discarded while parsing. + + + + + Internal-only property; provides extension identifiers to compatible messages while parsing. + + + + + Primitives for parsing protobuf wire format. + + + + + Reads a length for length-delimited data. + + + This is internally just reading a varint, but this method exists + to make the calling code clearer. + + + + + Parses the next tag. + If the end of logical stream was reached, an invalid tag of 0 is returned. + + + + + Peeks at the next tag in the stream. If it matches , + the tag is consumed and the method returns true; otherwise, the + stream is left in the original position and the method returns false. + + + + + Peeks at the next field tag. This is like calling , but the + tag is not consumed. (So a subsequent call to will return the + same value.) + + + + + Parses a raw varint. + + + + + Parses a raw Varint. If larger than 32 bits, discard the upper bits. + This method is optimised for the case where we've got lots of data in the buffer. + That means we can check the size just once, then just read directly from the buffer + without constant rechecking of the buffer length. + + + + + Parses a 32-bit little-endian integer. + + + + + Parses a 64-bit little-endian integer. + + + + + Parses a double value. + + + + + Parses a float value. + + + + + Reads a fixed size of bytes from the input. + + + the end of the stream or the current limit was reached + + + + + Reads and discards bytes. + + the end of the stream + or the current limit was reached + + + + Reads a string field value from the input. + + + + + Reads a bytes field value from the input. + + + + + Reads a UTF-8 string from the next "length" bytes. + + + the end of the stream or the current limit was reached + + + + + Reads a string assuming that it is spread across multiple spans in a . + + + + + Validates that the specified size doesn't exceed the current limit. If it does then remaining bytes + are skipped and an error is thrown. + + + + + Reads a varint from the input one byte at a time, so that it does not + read any bytes after the end of the varint. If you simply wrapped the + stream in a CodedInputStream and used ReadRawVarint32(Stream) + then you would probably end up reading past the end of the varint since + CodedInputStream buffers its input. + + + + + + + Decode a 32-bit value with ZigZag encoding. + + + ZigZag encodes signed integers into values that can be efficiently + encoded with varint. (Otherwise, negative values must be + sign-extended to 32 bits to be varint encoded, thus always taking + 5 bytes on the wire.) + + + + + Decode a 64-bit value with ZigZag encoding. + + + ZigZag encodes signed integers into values that can be efficiently + encoded with varint. (Otherwise, negative values must be + sign-extended to 64 bits to be varint encoded, thus always taking + 10 bytes on the wire.) + + + + + Checks whether there is known data available of the specified size remaining to parse. + When parsing from a Stream this can return false because we have no knowledge of the amount + of data remaining in the stream until it is read. + + + + + Checks whether there is known data available of the specified size remaining to parse + in the underlying data source. + When parsing from a Stream this will return false because we have no knowledge of the amount + of data remaining in the stream until it is read. + + + + + Read raw bytes of the specified length into a span. The amount of data available and the current limit should + be checked before calling this method. + + + + + Reading and skipping messages / groups + + + + + Skip a group. + + + + + Verifies that the last call to ReadTag() returned tag 0 - in other words, + we've reached the end of the stream when we expected to. + + The + tag read was not the one specified + + + + Fast parsing primitives for wrapper types + + + + + Helper methods for throwing exceptions when preconditions are not met. + + + This class is used internally and by generated code; it is not particularly + expected to be used from application code, although nothing prevents it + from being used that way. + + + + + Throws an ArgumentNullException if the given value is null, otherwise + return the value to the caller. + + + + + Throws an ArgumentNullException if the given value is null, otherwise + return the value to the caller. + + + This is equivalent to but without the type parameter + constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull + with a value type - but it gets in the way if either you want to use it with a nullable + value type, or you want to use it with an unconstrained type parameter. + + + + + Container for a set of custom options specified within a message, field etc. + + + + This type is publicly immutable, but internally mutable. It is only populated + by the descriptor parsing code - by the time any user code is able to see an instance, + it will be fully initialized. + + + If an option is requested using the incorrect method, an answer may still be returned: all + of the numeric types are represented internally using 64-bit integers, for example. It is up to + the caller to ensure that they make the appropriate method call for the option they're interested in. + Note that enum options are simply stored as integers, so the value should be fetched using + and then cast appropriately. + + + Repeated options are currently not supported. Asking for a single value of an option + which was actually repeated will return the last value, except for message types where + all the set values are merged together. + + + + + + Retrieves a Boolean value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 32-bit integer value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 64-bit integer value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves an unsigned 32-bit integer value for the specified option field, + assuming a fixed-length representation. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves an unsigned 64-bit integer value for the specified option field, + assuming a fixed-length representation. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 32-bit integer value for the specified option field, + assuming a fixed-length representation. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 64-bit integer value for the specified option field, + assuming a fixed-length representation. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 32-bit integer value for the specified option field, + assuming a zigzag encoding. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a signed 64-bit integer value for the specified option field, + assuming a zigzag encoding. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves an unsigned 32-bit integer value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves an unsigned 64-bit integer value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a 32-bit floating point value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a 64-bit floating point value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a string value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a bytes value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + + Retrieves a message value for the specified option field. + + The field to fetch the value for. + The output variable to populate. + true if a suitable value for the field was found; false otherwise. + + + Holder for reflection information generated from google/protobuf/descriptor.proto + + + File descriptor for google/protobuf/descriptor.proto + + + + The protocol compiler can output a FileDescriptorSet containing the .proto + files it parses. + + + + Field number for the "file" field. + + + + Describes a complete .proto file. + + + + Field number for the "name" field. + + + + file name, relative to root of source tree + + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "package" field. + + + + e.g. "foo", "foo.bar", etc. + + + + Gets whether the "package" field is set + + + Clears the value of the "package" field + + + Field number for the "dependency" field. + + + + Names of files imported by this file. + + + + Field number for the "public_dependency" field. + + + + Indexes of the public imported files in the dependency list above. + + + + Field number for the "weak_dependency" field. + + + + Indexes of the weak imported files in the dependency list. + For Google-internal migration only. Do not use. + + + + Field number for the "message_type" field. + + + + All top-level definitions in this file. + + + + Field number for the "enum_type" field. + + + Field number for the "service" field. + + + Field number for the "extension" field. + + + Field number for the "options" field. + + + Field number for the "source_code_info" field. + + + + This field contains optional information about the original source code. + You may safely remove this entire field without harming runtime + functionality of the descriptors -- the information is needed only by + development tools. + + + + Field number for the "syntax" field. + + + + The syntax of the proto file. + The supported values are "proto2" and "proto3". + + + + Gets whether the "syntax" field is set + + + Clears the value of the "syntax" field + + + + Describes a message type. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "field" field. + + + Field number for the "extension" field. + + + Field number for the "nested_type" field. + + + Field number for the "enum_type" field. + + + Field number for the "extension_range" field. + + + Field number for the "oneof_decl" field. + + + Field number for the "options" field. + + + Field number for the "reserved_range" field. + + + Field number for the "reserved_name" field. + + + + Reserved field names, which may not be used by fields in the same message. + A given name may only be reserved once. + + + + Container for nested types declared in the DescriptorProto message type. + + + Field number for the "start" field. + + + + Inclusive. + + + + Gets whether the "start" field is set + + + Clears the value of the "start" field + + + Field number for the "end" field. + + + + Exclusive. + + + + Gets whether the "end" field is set + + + Clears the value of the "end" field + + + Field number for the "options" field. + + + + Range of reserved tag numbers. Reserved tag numbers may not be used by + fields or extension ranges in the same message. Reserved ranges may + not overlap. + + + + Field number for the "start" field. + + + + Inclusive. + + + + Gets whether the "start" field is set + + + Clears the value of the "start" field + + + Field number for the "end" field. + + + + Exclusive. + + + + Gets whether the "end" field is set + + + Clears the value of the "end" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + + Describes a field within a message. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "number" field. + + + Gets whether the "number" field is set + + + Clears the value of the "number" field + + + Field number for the "label" field. + + + Gets whether the "label" field is set + + + Clears the value of the "label" field + + + Field number for the "type" field. + + + + If type_name is set, this need not be set. If both this and type_name + are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + + + + Gets whether the "type" field is set + + + Clears the value of the "type" field + + + Field number for the "type_name" field. + + + + For message and enum types, this is the name of the type. If the name + starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + rules are used to find the type (i.e. first the nested types within this + message are searched, then within the parent, on up to the root + namespace). + + + + Gets whether the "type_name" field is set + + + Clears the value of the "type_name" field + + + Field number for the "extendee" field. + + + + For extensions, this is the name of the type being extended. It is + resolved in the same manner as type_name. + + + + Gets whether the "extendee" field is set + + + Clears the value of the "extendee" field + + + Field number for the "default_value" field. + + + + For numeric types, contains the original text representation of the value. + For booleans, "true" or "false". + For strings, contains the default text contents (not escaped in any way). + For bytes, contains the C escaped value. All bytes >= 128 are escaped. + + + + Gets whether the "default_value" field is set + + + Clears the value of the "default_value" field + + + Field number for the "oneof_index" field. + + + + If set, gives the index of a oneof in the containing type's oneof_decl + list. This field is a member of that oneof. + + + + Gets whether the "oneof_index" field is set + + + Clears the value of the "oneof_index" field + + + Field number for the "json_name" field. + + + + JSON name of this field. The value is set by protocol compiler. If the + user has set a "json_name" option on this field, that option's value + will be used. Otherwise, it's deduced from the field's name by converting + it to camelCase. + + + + Gets whether the "json_name" field is set + + + Clears the value of the "json_name" field + + + Field number for the "options" field. + + + Field number for the "proto3_optional" field. + + + + If true, this is a proto3 "optional". When a proto3 field is optional, it + tracks presence regardless of field type. + + When proto3_optional is true, this field must be belong to a oneof to + signal to old proto3 clients that presence is tracked for this field. This + oneof is known as a "synthetic" oneof, and this field must be its sole + member (each proto3 optional field gets its own synthetic oneof). Synthetic + oneofs exist in the descriptor only, and do not generate any API. Synthetic + oneofs must be ordered after all "real" oneofs. + + For message fields, proto3_optional doesn't create any semantic change, + since non-repeated message fields always track presence. However it still + indicates the semantic detail of whether the user wrote "optional" or not. + This can be useful for round-tripping the .proto file. For consistency we + give message fields a synthetic oneof also, even though it is not required + to track presence. This is especially important because the parser can't + tell if a field is a message or an enum, so it must always create a + synthetic oneof. + + Proto2 optional fields do not set this flag, because they already indicate + optional with `LABEL_OPTIONAL`. + + + + Gets whether the "proto3_optional" field is set + + + Clears the value of the "proto3_optional" field + + + Container for nested types declared in the FieldDescriptorProto message type. + + + + 0 is reserved for errors. + Order is weird for historical reasons. + + + + + Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + negative values are likely. + + + + + Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + negative values are likely. + + + + + Tag-delimited aggregate. + Group type is deprecated and not supported in proto3. However, Proto3 + implementations should still be able to parse the group wire format and + treat group fields as unknown fields. + + + + + Length-delimited aggregate. + + + + + New in version 2. + + + + + Uses ZigZag encoding. + + + + + Uses ZigZag encoding. + + + + + 0 is reserved for errors + + + + + Describes a oneof. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "options" field. + + + + Describes an enum type. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "value" field. + + + Field number for the "options" field. + + + Field number for the "reserved_range" field. + + + + Range of reserved numeric values. Reserved numeric values may not be used + by enum values in the same enum declaration. Reserved ranges may not + overlap. + + + + Field number for the "reserved_name" field. + + + + Reserved enum value names, which may not be reused. A given name may only + be reserved once. + + + + Container for nested types declared in the EnumDescriptorProto message type. + + + + Range of reserved numeric values. Reserved values may not be used by + entries in the same enum. Reserved ranges may not overlap. + + Note that this is distinct from DescriptorProto.ReservedRange in that it + is inclusive such that it can appropriately represent the entire int32 + domain. + + + + Field number for the "start" field. + + + + Inclusive. + + + + Gets whether the "start" field is set + + + Clears the value of the "start" field + + + Field number for the "end" field. + + + + Inclusive. + + + + Gets whether the "end" field is set + + + Clears the value of the "end" field + + + + Describes a value within an enum. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "number" field. + + + Gets whether the "number" field is set + + + Clears the value of the "number" field + + + Field number for the "options" field. + + + + Describes a service. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "method" field. + + + Field number for the "options" field. + + + + Describes a method of a service. + + + + Field number for the "name" field. + + + Gets whether the "name" field is set + + + Clears the value of the "name" field + + + Field number for the "input_type" field. + + + + Input and output type names. These are resolved in the same way as + FieldDescriptorProto.type_name, but must refer to a message type. + + + + Gets whether the "input_type" field is set + + + Clears the value of the "input_type" field + + + Field number for the "output_type" field. + + + Gets whether the "output_type" field is set + + + Clears the value of the "output_type" field + + + Field number for the "options" field. + + + Field number for the "client_streaming" field. + + + + Identifies if client streams multiple client messages + + + + Gets whether the "client_streaming" field is set + + + Clears the value of the "client_streaming" field + + + Field number for the "server_streaming" field. + + + + Identifies if server streams multiple server messages + + + + Gets whether the "server_streaming" field is set + + + Clears the value of the "server_streaming" field + + + Field number for the "java_package" field. + + + + Sets the Java package where classes generated from this .proto will be + placed. By default, the proto package is used, but this is often + inappropriate because proto packages do not normally start with backwards + domain names. + + + + Gets whether the "java_package" field is set + + + Clears the value of the "java_package" field + + + Field number for the "java_outer_classname" field. + + + + Controls the name of the wrapper Java class generated for the .proto file. + That class will always contain the .proto file's getDescriptor() method as + well as any top-level extensions defined in the .proto file. + If java_multiple_files is disabled, then all the other classes from the + .proto file will be nested inside the single wrapper outer class. + + + + Gets whether the "java_outer_classname" field is set + + + Clears the value of the "java_outer_classname" field + + + Field number for the "java_multiple_files" field. + + + + If enabled, then the Java code generator will generate a separate .java + file for each top-level message, enum, and service defined in the .proto + file. Thus, these types will *not* be nested inside the wrapper class + named by java_outer_classname. However, the wrapper class will still be + generated to contain the file's getDescriptor() method as well as any + top-level extensions defined in the file. + + + + Gets whether the "java_multiple_files" field is set + + + Clears the value of the "java_multiple_files" field + + + Field number for the "java_generate_equals_and_hash" field. + + + + This option does nothing. + + + + Gets whether the "java_generate_equals_and_hash" field is set + + + Clears the value of the "java_generate_equals_and_hash" field + + + Field number for the "java_string_check_utf8" field. + + + + If set true, then the Java2 code generator will generate code that + throws an exception whenever an attempt is made to assign a non-UTF-8 + byte sequence to a string field. + Message reflection will do the same. + However, an extension field still accepts non-UTF-8 byte sequences. + This option has no effect on when used with the lite runtime. + + + + Gets whether the "java_string_check_utf8" field is set + + + Clears the value of the "java_string_check_utf8" field + + + Field number for the "optimize_for" field. + + + Gets whether the "optimize_for" field is set + + + Clears the value of the "optimize_for" field + + + Field number for the "go_package" field. + + + + Sets the Go package where structs generated from this .proto will be + placed. If omitted, the Go package will be derived from the following: + - The basename of the package import path, if provided. + - Otherwise, the package statement in the .proto file, if present. + - Otherwise, the basename of the .proto file, without extension. + + + + Gets whether the "go_package" field is set + + + Clears the value of the "go_package" field + + + Field number for the "cc_generic_services" field. + + + + Should generic services be generated in each language? "Generic" services + are not specific to any particular RPC system. They are generated by the + main code generators in each language (without additional plugins). + Generic services were the only kind of service generation supported by + early versions of google.protobuf. + + Generic services are now considered deprecated in favor of using plugins + that generate code specific to your particular RPC system. Therefore, + these default to false. Old code which depends on generic services should + explicitly set them to true. + + + + Gets whether the "cc_generic_services" field is set + + + Clears the value of the "cc_generic_services" field + + + Field number for the "java_generic_services" field. + + + Gets whether the "java_generic_services" field is set + + + Clears the value of the "java_generic_services" field + + + Field number for the "py_generic_services" field. + + + Gets whether the "py_generic_services" field is set + + + Clears the value of the "py_generic_services" field + + + Field number for the "php_generic_services" field. + + + Gets whether the "php_generic_services" field is set + + + Clears the value of the "php_generic_services" field + + + Field number for the "deprecated" field. + + + + Is this file deprecated? + Depending on the target platform, this can emit Deprecated annotations + for everything in the file, or it will be completely ignored; in the very + least, this is a formalization for deprecating files. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "cc_enable_arenas" field. + + + + Enables the use of arenas for the proto messages in this file. This applies + only to generated classes for C++. + + + + Gets whether the "cc_enable_arenas" field is set + + + Clears the value of the "cc_enable_arenas" field + + + Field number for the "objc_class_prefix" field. + + + + Sets the objective c class prefix which is prepended to all objective c + generated classes from this .proto. There is no default. + + + + Gets whether the "objc_class_prefix" field is set + + + Clears the value of the "objc_class_prefix" field + + + Field number for the "csharp_namespace" field. + + + + Namespace for generated classes; defaults to the package. + + + + Gets whether the "csharp_namespace" field is set + + + Clears the value of the "csharp_namespace" field + + + Field number for the "swift_prefix" field. + + + + By default Swift generators will take the proto package and CamelCase it + replacing '.' with underscore and use that to prefix the types/symbols + defined. When this options is provided, they will use this value instead + to prefix the types/symbols defined. + + + + Gets whether the "swift_prefix" field is set + + + Clears the value of the "swift_prefix" field + + + Field number for the "php_class_prefix" field. + + + + Sets the php class prefix which is prepended to all php generated classes + from this .proto. Default is empty. + + + + Gets whether the "php_class_prefix" field is set + + + Clears the value of the "php_class_prefix" field + + + Field number for the "php_namespace" field. + + + + Use this option to change the namespace of php generated classes. Default + is empty. When this option is empty, the package name will be used for + determining the namespace. + + + + Gets whether the "php_namespace" field is set + + + Clears the value of the "php_namespace" field + + + Field number for the "php_metadata_namespace" field. + + + + Use this option to change the namespace of php generated metadata classes. + Default is empty. When this option is empty, the proto file name will be + used for determining the namespace. + + + + Gets whether the "php_metadata_namespace" field is set + + + Clears the value of the "php_metadata_namespace" field + + + Field number for the "ruby_package" field. + + + + Use this option to change the package of ruby generated classes. Default + is empty. When this option is not set, the package name will be used for + determining the ruby package. + + + + Gets whether the "ruby_package" field is set + + + Clears the value of the "ruby_package" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. + See the documentation for the "Options" section above. + + + + Container for nested types declared in the FileOptions message type. + + + + Generated classes can be optimized for speed or code size. + + + + + Generate complete code for parsing, serialization, + + + + + etc. + + + + + Generate code using MessageLite and the lite runtime. + + + + Field number for the "message_set_wire_format" field. + + + + Set true to use the old proto1 MessageSet wire format for extensions. + This is provided for backwards-compatibility with the MessageSet wire + format. You should not use this for any other reason: It's less + efficient, has fewer features, and is more complicated. + + The message must be defined exactly as follows: + message Foo { + option message_set_wire_format = true; + extensions 4 to max; + } + Note that the message cannot have any defined fields; MessageSets only + have extensions. + + All extensions of your type must be singular messages; e.g. they cannot + be int32s, enums, or repeated messages. + + Because this is an option, the above two restrictions are not enforced by + the protocol compiler. + + + + Gets whether the "message_set_wire_format" field is set + + + Clears the value of the "message_set_wire_format" field + + + Field number for the "no_standard_descriptor_accessor" field. + + + + Disables the generation of the standard "descriptor()" accessor, which can + conflict with a field of the same name. This is meant to make migration + from proto1 easier; new code should avoid fields named "descriptor". + + + + Gets whether the "no_standard_descriptor_accessor" field is set + + + Clears the value of the "no_standard_descriptor_accessor" field + + + Field number for the "deprecated" field. + + + + Is this message deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the message, or it will be completely ignored; in the very least, + this is a formalization for deprecating messages. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "map_entry" field. + + + + Whether the message is an automatically generated map entry type for the + maps field. + + For maps fields: + map<KeyType, ValueType> map_field = 1; + The parsed descriptor looks like: + message MapFieldEntry { + option map_entry = true; + optional KeyType key = 1; + optional ValueType value = 2; + } + repeated MapFieldEntry map_field = 1; + + Implementations may choose not to generate the map_entry=true message, but + use a native map in the target language to hold the keys and values. + The reflection APIs in such implementations still need to work as + if the field is a repeated message field. + + NOTE: Do not set the option in .proto files. Always use the maps syntax + instead. The option should only be implicitly set by the proto compiler + parser. + + + + Gets whether the "map_entry" field is set + + + Clears the value of the "map_entry" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "ctype" field. + + + + The ctype option instructs the C++ code generator to use a different + representation of the field than it normally would. See the specific + options below. This option is not yet implemented in the open source + release -- sorry, we'll try to include it in a future version! + + + + Gets whether the "ctype" field is set + + + Clears the value of the "ctype" field + + + Field number for the "packed" field. + + + + The packed option can be enabled for repeated primitive fields to enable + a more efficient representation on the wire. Rather than repeatedly + writing the tag and type for each element, the entire array is encoded as + a single length-delimited blob. In proto3, only explicit setting it to + false will avoid using packed encoding. + + + + Gets whether the "packed" field is set + + + Clears the value of the "packed" field + + + Field number for the "jstype" field. + + + + The jstype option determines the JavaScript type used for values of the + field. The option is permitted only for 64 bit integral and fixed types + (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + is represented as JavaScript string, which avoids loss of precision that + can happen when a large value is converted to a floating point JavaScript. + Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + use the JavaScript "number" type. The behavior of the default option + JS_NORMAL is implementation dependent. + + This option is an enum to permit additional types to be added, e.g. + goog.math.Integer. + + + + Gets whether the "jstype" field is set + + + Clears the value of the "jstype" field + + + Field number for the "lazy" field. + + + + Should this field be parsed lazily? Lazy applies only to message-type + fields. It means that when the outer message is initially parsed, the + inner message's contents will not be parsed but instead stored in encoded + form. The inner message will actually be parsed when it is first accessed. + + This is only a hint. Implementations are free to choose whether to use + eager or lazy parsing regardless of the value of this option. However, + setting this option true suggests that the protocol author believes that + using lazy parsing on this field is worth the additional bookkeeping + overhead typically needed to implement it. + + This option does not affect the public interface of any generated code; + all method signatures remain the same. Furthermore, thread-safety of the + interface is not affected by this option; const methods remain safe to + call from multiple threads concurrently, while non-const methods continue + to require exclusive access. + + Note that implementations may choose not to check required fields within + a lazy sub-message. That is, calling IsInitialized() on the outer message + may return true even if the inner message has missing required fields. + This is necessary because otherwise the inner message would have to be + parsed in order to perform the check, defeating the purpose of lazy + parsing. An implementation which chooses not to check required fields + must be consistent about it. That is, for any particular sub-message, the + implementation must either *always* check its required fields, or *never* + check its required fields, regardless of whether or not the message has + been parsed. + + As of 2021, lazy does no correctness checks on the byte stream during + parsing. This may lead to crashes if and when an invalid byte stream is + finally parsed upon access. + + TODO(b/211906113): Enable validation on lazy fields. + + + + Gets whether the "lazy" field is set + + + Clears the value of the "lazy" field + + + Field number for the "unverified_lazy" field. + + + + unverified_lazy does no correctness checks on the byte stream. This should + only be used where lazy with verification is prohibitive for performance + reasons. + + + + Gets whether the "unverified_lazy" field is set + + + Clears the value of the "unverified_lazy" field + + + Field number for the "deprecated" field. + + + + Is this field deprecated? + Depending on the target platform, this can emit Deprecated annotations + for accessors, or it will be completely ignored; in the very least, this + is a formalization for deprecating fields. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "weak" field. + + + + For Google-internal migration only. Do not use. + + + + Gets whether the "weak" field is set + + + Clears the value of the "weak" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Container for nested types declared in the FieldOptions message type. + + + + Default mode. + + + + + Use the default type. + + + + + Use JavaScript strings. + + + + + Use JavaScript numbers. + + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "allow_alias" field. + + + + Set this option to true to allow mapping different tag names to the same + value. + + + + Gets whether the "allow_alias" field is set + + + Clears the value of the "allow_alias" field + + + Field number for the "deprecated" field. + + + + Is this enum deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the enum, or it will be completely ignored; in the very least, this + is a formalization for deprecating enums. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "deprecated" field. + + + + Is this enum value deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the enum value, or it will be completely ignored; in the very least, + this is a formalization for deprecating enum values. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "deprecated" field. + + + + Is this service deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the service, or it will be completely ignored; in the very least, + this is a formalization for deprecating services. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Field number for the "deprecated" field. + + + + Is this method deprecated? + Depending on the target platform, this can emit Deprecated annotations + for the method, or it will be completely ignored; in the very least, + this is a formalization for deprecating methods. + + + + Gets whether the "deprecated" field is set + + + Clears the value of the "deprecated" field + + + Field number for the "idempotency_level" field. + + + Gets whether the "idempotency_level" field is set + + + Clears the value of the "idempotency_level" field + + + Field number for the "uninterpreted_option" field. + + + + The parser stores options it doesn't recognize here. See above. + + + + Container for nested types declared in the MethodOptions message type. + + + + Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + or neither? HTTP based RPC implementation may choose GET verb for safe + methods, and PUT verb for idempotent methods instead of the default POST. + + + + + implies idempotent + + + + + idempotent, but may have side effects + + + + + A message representing a option the parser does not recognize. This only + appears in options protos created by the compiler::Parser class. + DescriptorPool resolves these when building Descriptor objects. Therefore, + options protos in descriptor objects (e.g. returned by Descriptor::options(), + or produced by Descriptor::CopyTo()) will never have UninterpretedOptions + in them. + + + + Field number for the "name" field. + + + Field number for the "identifier_value" field. + + + + The value of the uninterpreted option, in whatever type the tokenizer + identified it as during parsing. Exactly one of these should be set. + + + + Gets whether the "identifier_value" field is set + + + Clears the value of the "identifier_value" field + + + Field number for the "positive_int_value" field. + + + Gets whether the "positive_int_value" field is set + + + Clears the value of the "positive_int_value" field + + + Field number for the "negative_int_value" field. + + + Gets whether the "negative_int_value" field is set + + + Clears the value of the "negative_int_value" field + + + Field number for the "double_value" field. + + + Gets whether the "double_value" field is set + + + Clears the value of the "double_value" field + + + Field number for the "string_value" field. + + + Gets whether the "string_value" field is set + + + Clears the value of the "string_value" field + + + Field number for the "aggregate_value" field. + + + Gets whether the "aggregate_value" field is set + + + Clears the value of the "aggregate_value" field + + + Container for nested types declared in the UninterpretedOption message type. + + + + The name of the uninterpreted option. Each string represents a segment in + a dot-separated name. is_extension is true iff a segment represents an + extension (denoted with parentheses in options specs in .proto files). + E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents + "foo.(bar.baz).moo". + + + + Field number for the "name_part" field. + + + Gets whether the "name_part" field is set + + + Clears the value of the "name_part" field + + + Field number for the "is_extension" field. + + + Gets whether the "is_extension" field is set + + + Clears the value of the "is_extension" field + + + + Encapsulates information about the original source file from which a + FileDescriptorProto was generated. + + + + Field number for the "location" field. + + + + A Location identifies a piece of source code in a .proto file which + corresponds to a particular definition. This information is intended + to be useful to IDEs, code indexers, documentation generators, and similar + tools. + + For example, say we have a file like: + message Foo { + optional string foo = 1; + } + Let's look at just the field definition: + optional string foo = 1; + ^ ^^ ^^ ^ ^^^ + a bc de f ghi + We have the following locations: + span path represents + [a,i) [ 4, 0, 2, 0 ] The whole field definition. + [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + + Notes: + - A location may refer to a repeated field itself (i.e. not to any + particular index within it). This is used whenever a set of elements are + logically enclosed in a single code segment. For example, an entire + extend block (possibly containing multiple extension definitions) will + have an outer location whose path refers to the "extensions" repeated + field without an index. + - Multiple locations may have the same path. This happens when a single + logical declaration is spread out across multiple places. The most + obvious example is the "extend" block again -- there may be multiple + extend blocks in the same scope, each of which will have the same path. + - A location's span is not always a subset of its parent's span. For + example, the "extendee" of an extension declaration appears at the + beginning of the "extend" block and is shared by all extensions within + the block. + - Just because a location's span is a subset of some other location's span + does not mean that it is a descendant. For example, a "group" defines + both a type and a field in a single declaration. Thus, the locations + corresponding to the type and field and their components will overlap. + - Code which tries to interpret locations should probably be designed to + ignore those that it doesn't understand, as more types of locations could + be recorded in the future. + + + + Container for nested types declared in the SourceCodeInfo message type. + + + Field number for the "path" field. + + + + Identifies which part of the FileDescriptorProto was defined at this + location. + + Each element is a field number or an index. They form a path from + the root FileDescriptorProto to the place where the definition occurs. + For example, this path: + [ 4, 3, 2, 7, 1 ] + refers to: + file.message_type(3) // 4, 3 + .field(7) // 2, 7 + .name() // 1 + This is because FileDescriptorProto.message_type has field number 4: + repeated DescriptorProto message_type = 4; + and DescriptorProto.field has field number 2: + repeated FieldDescriptorProto field = 2; + and FieldDescriptorProto.name has field number 1: + optional string name = 1; + + Thus, the above path gives the location of a field name. If we removed + the last element: + [ 4, 3, 2, 7 ] + this path refers to the whole field declaration (from the beginning + of the label to the terminating semicolon). + + + + Field number for the "span" field. + + + + Always has exactly three or four elements: start line, start column, + end line (optional, otherwise assumed same as start line), end column. + These are packed into a single field for efficiency. Note that line + and column numbers are zero-based -- typically you will want to add + 1 to each before displaying to a user. + + + + Field number for the "leading_comments" field. + + + + If this SourceCodeInfo represents a complete declaration, these are any + comments appearing before and after the declaration which appear to be + attached to the declaration. + + A series of line comments appearing on consecutive lines, with no other + tokens appearing on those lines, will be treated as a single comment. + + leading_detached_comments will keep paragraphs of comments that appear + before (but not connected to) the current element. Each paragraph, + separated by empty lines, will be one comment element in the repeated + field. + + Only the comment content is provided; comment markers (e.g. //) are + stripped out. For block comments, leading whitespace and an asterisk + will be stripped from the beginning of each line other than the first. + Newlines are included in the output. + + Examples: + + optional int32 foo = 1; // Comment attached to foo. + // Comment attached to bar. + optional int32 bar = 2; + + optional string baz = 3; + // Comment attached to baz. + // Another line attached to baz. + + // Comment attached to moo. + // + // Another line attached to moo. + optional double moo = 4; + + // Detached comment for corge. This is not leading or trailing comments + // to moo or corge because there are blank lines separating it from + // both. + + // Detached comment for corge paragraph 2. + + optional string corge = 5; + /* Block comment attached + * to corge. Leading asterisks + * will be removed. */ + /* Block comment attached to + * grault. */ + optional int32 grault = 6; + + // ignored detached comments. + + + + Gets whether the "leading_comments" field is set + + + Clears the value of the "leading_comments" field + + + Field number for the "trailing_comments" field. + + + Gets whether the "trailing_comments" field is set + + + Clears the value of the "trailing_comments" field + + + Field number for the "leading_detached_comments" field. + + + + Describes the relationship between generated code and its original source + file. A GeneratedCodeInfo message is associated with only one generated + source file, but may contain references to different source .proto files. + + + + Field number for the "annotation" field. + + + + An Annotation connects some span of text in generated code to an element + of its generating .proto file. + + + + Container for nested types declared in the GeneratedCodeInfo message type. + + + Field number for the "path" field. + + + + Identifies the element in the original source .proto file. This field + is formatted the same as SourceCodeInfo.Location.path. + + + + Field number for the "source_file" field. + + + + Identifies the filesystem path to the original source .proto. + + + + Gets whether the "source_file" field is set + + + Clears the value of the "source_file" field + + + Field number for the "begin" field. + + + + Identifies the starting offset in bytes in the generated code + that relates to the identified object. + + + + Gets whether the "begin" field is set + + + Clears the value of the "begin" field + + + Field number for the "end" field. + + + + Identifies the ending offset in bytes in the generated code that + relates to the identified offset. The end offset should be one past + the last relevant byte (so the length of the text = end - begin). + + + + Gets whether the "end" field is set + + + Clears the value of the "end" field + + + + Base class for nearly all descriptors, providing common functionality. + + + + + The index of this descriptor within its parent descriptor. + + + This returns the index of this descriptor within its parent, for + this descriptor's type. (There can be duplicate values for different + types, e.g. one enum type with index 0 and one message type with index 0.) + + + + + Returns the name of the entity (field, message etc) being described. + + + + + The fully qualified name of the descriptor's target. + + + + + The file this descriptor was declared in. + + + + + The declaration information about the descriptor, or null if no declaration information + is available for this descriptor. + + + This information is typically only available for dynamically loaded descriptors, + for example within a protoc plugin where the full descriptors, including source info, + are passed to the code by protoc. + + + + + Retrieves the list of nested descriptors corresponding to the given field number, if any. + If the field is unknown or not a nested descriptor list, return null to terminate the search. + The default implementation returns null. + + + + + Provides additional information about the declaration of a descriptor, + such as source location and comments. + + + + + The descriptor this declaration relates to. + + + + + The start line of the declaration within the source file. This value is 1-based. + + + + + The start column of the declaration within the source file. This value is 1-based. + + + + + // The end line of the declaration within the source file. This value is 1-based. + + + + + The end column of the declaration within the source file. This value is 1-based, and + exclusive. (The final character of the declaration is on the column before this value.) + + + + + Comments appearing before the declaration. Never null, but may be empty. Multi-line comments + are represented as a newline-separated string. Leading whitespace and the comment marker ("//") + are removed from each line. + + + + + Comments appearing after the declaration. Never null, but may be empty. Multi-line comments + are represented as a newline-separated string. Leading whitespace and the comment marker ("//") + are removed from each line. + + + + + Comments appearing before the declaration, but separated from it by blank + lines. Each string represents a newline-separated paragraph of comments. + Leading whitespace and the comment marker ("//") are removed from each line. + The list is never null, but may be empty. Likewise each element is never null, but may be empty. + + + + + Contains lookup tables containing all the descriptors defined in a particular file. + + + + + Finds a symbol of the given name within the pool. + + The type of symbol to look for + Fully-qualified name to look up + The symbol with the given name and type, + or null if the symbol doesn't exist or has the wrong type + + + + Adds a package to the symbol tables. If a package by the same name + already exists, that is fine, but if some other kind of symbol + exists under the same name, an exception is thrown. If the package + has multiple components, this also adds the parent package(s). + + + + + Adds a symbol to the symbol table. + + The symbol already existed + in the symbol table. + + + + Verifies that the descriptor's name is valid (i.e. it contains + only letters, digits and underscores, and does not start with a digit). + + + + + + Returns the field with the given number in the given descriptor, + or null if it can't be found. + + + + + Adds a field to the fieldsByNumber table. + + A field with the same + containing type and number already exists. + + + + Adds an enum value to the enumValuesByNumber table. If an enum value + with the same type and number already exists, this method does nothing. + (This is allowed; the first value defined with the number takes precedence.) + + + + + Looks up a descriptor by name, relative to some other descriptor. + The name may be fully-qualified (with a leading '.'), partially-qualified, + or unqualified. C++-like name lookup semantics are used to search for the + matching descriptor. + + + This isn't heavily optimized, but it's only used during cross linking anyway. + If it starts being used more widely, we should look at performance more carefully. + + + + + Internal class containing utility methods when working with descriptors. + + + + + Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert + arrays. + + + + + Converts the given array into a read-only list, applying the specified conversion to + each input element. + + + + + Thrown when building descriptors fails because the source DescriptorProtos + are not valid. + + + + + The full name of the descriptor where the error occurred. + + + + + A human-readable description of the error. (The Message property + is made up of the descriptor's name and this description.) + + + + + Descriptor for an enum type in a .proto file. + + + + + Returns a clone of the underlying describing this enum. + Note that a copy is taken every time this method is called, so clients using it frequently + (and not modifying it) may want to cache the returned value. + + A protobuf representation of this enum descriptor. + + + + The brief name of the descriptor's target. + + + + + The CLR type for this enum. For generated code, this will be a CLR enum type. + + + + + If this is a nested type, get the outer descriptor, otherwise null. + + + + + An unmodifiable list of defined value descriptors for this enum. + + + + + Finds an enum value by number. If multiple enum values have the + same number, this returns the first defined value with that number. + If there is no value for the given number, this returns null. + + + + + Finds an enum value by name. + + The unqualified name of the value (e.g. "FOO"). + The value's descriptor, or null if not found. + + + + The (possibly empty) set of custom options for this enum. + + + + + The EnumOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value enum option for this descriptor + + + + + Gets a repeated value enum option for this descriptor + + + + + Descriptor for a single enum value within an enum in a .proto file. + + + + + Returns a clone of the underlying describing this enum value. + Note that a copy is taken every time this method is called, so clients using it frequently + (and not modifying it) may want to cache the returned value. + + A protobuf representation of this enum value descriptor. + + + + Returns the name of the enum value described by this object. + + + + + Returns the number associated with this enum value. + + + + + Returns the enum descriptor that this value is part of. + + + + + The (possibly empty) set of custom options for this enum value. + + + + + The EnumValueOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value enum value option for this descriptor + + + + + Gets a repeated value enum value option for this descriptor + + + + + A collection to simplify retrieving the descriptors of extensions in a descriptor for a message + + + + + Returns a readonly list of all the extensions defined in this type in + the order they were defined in the source .proto file + + + + + Returns a readonly list of all the extensions define in this type that extend + the provided descriptor type in the order they were defined in the source .proto file + + + + + Returns a readonly list of all the extensions define in this type that extend + the provided descriptor type in ascending field order + + + + + Base class for field accessors. + + + + + Descriptor for a field or extension within a message in a .proto file. + + + + + Get the field's containing message type, or null if it is a field defined at the top level of a file as an extension. + + + + + Returns the oneof containing this field, or null if it is not part of a oneof. + + + + + Returns the oneof containing this field if it's a "real" oneof, or null if either this + field is not part of a oneof, or the oneof is synthetic. + + + + + The effective JSON name for this field. This is usually the lower-camel-cased form of the field name, + but can be overridden using the json_name option in the .proto file. + + + + + The name of the property in the ContainingType.ClrType class. + + + + + Indicates whether this field supports presence, either implicitly (e.g. due to it being a message + type field) or explicitly via Has/Clear members. If this returns true, it is safe to call + and + on this field's accessor with a suitable message. + + + + + Returns a clone of the underlying describing this field. + Note that a copy is taken every time this method is called, so clients using it frequently + (and not modifying it) may want to cache the returned value. + + A protobuf representation of this field descriptor. + + + + An extension identifier for this field, or null if this field isn't an extension. + + + + + The brief name of the descriptor's target. + + + + + Returns the accessor for this field. + + + + While a describes the field, it does not provide + any way of obtaining or changing the value of the field within a specific message; + that is the responsibility of the accessor. + + + In descriptors for generated code, the value returned by this property will be non-null for all + regular fields. However, if a message containing a map field is introspected, the list of nested messages will include + an auto-generated nested key/value pair message for the field. This is not represented in any + generated type, and the value of the map field itself is represented by a dictionary in the + reflection API. There are never instances of those "hidden" messages, so no accessor is provided + and this property will return null. + + + In dynamically loaded descriptors, the value returned by this property will current be null; + if and when dynamic messages are supported, it will return a suitable accessor to work with + them. + + + + + + Maps a field type as included in the .proto file to a FieldType. + + + + + Returns true if this field is a repeated field; false otherwise. + + + + + Returns true if this field is a required field; false otherwise. + + + + + Returns true if this field is a map field; false otherwise. + + + + + Returns true if this field is a packed, repeated field; false otherwise. + + + + + Returns true if this field extends another message type; false otherwise. + + + + + Returns the type of the field. + + + + + Returns the field number declared in the proto file. + + + + + Compares this descriptor with another one, ordering in "canonical" order + which simply means ascending order by field number. + must be a field of the same type, i.e. the of + both fields must be the same. + + + + + For enum fields, returns the field's type. + + + + + For embedded message and group fields, returns the field's type. + + + + + For extension fields, returns the extended type + + + + + The (possibly empty) set of custom options for this field. + + + + + The FieldOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value field option for this descriptor + + + + + Gets a repeated value field option for this descriptor + + + + + Look up and cross-link all field types etc. + + + + + Enumeration of all the possible field types. + + + + + The double field type. + + + + + The float field type. + + + + + The int64 field type. + + + + + The uint64 field type. + + + + + The int32 field type. + + + + + The fixed64 field type. + + + + + The fixed32 field type. + + + + + The bool field type. + + + + + The string field type. + + + + + The field type used for groups. + + + + + The field type used for message fields. + + + + + The bytes field type. + + + + + The uint32 field type. + + + + + The sfixed32 field type. + + + + + The sfixed64 field type. + + + + + The sint32 field type. + + + + + The sint64 field type. + + + + + The field type used for enum fields. + + + + + The syntax of a .proto file + + + + + Proto2 syntax + + + + + Proto3 syntax + + + + + An unknown declared syntax + + + + + Describes a .proto file, including everything defined within. + IDescriptor is implemented such that the File property returns this descriptor, + and the FullName is the same as the Name. + + + + + Computes the full name of a descriptor within this file, with an optional parent message. + + + + + Extracts public dependencies from direct dependencies. This is a static method despite its + first parameter, as the value we're in the middle of constructing is only used for exceptions. + + + + + The descriptor in its protocol message representation. + + + + + Returns a clone of the underlying describing this file. + Note that a copy is taken every time this method is called, so clients using it frequently + (and not modifying it) may want to cache the returned value. + + A protobuf representation of this file descriptor. + + + + The syntax of the file + + + + + The file name. + + + + + The package as declared in the .proto file. This may or may not + be equivalent to the .NET namespace of the generated classes. + + + + + Unmodifiable list of top-level message types declared in this file. + + + + + Unmodifiable list of top-level enum types declared in this file. + + + + + Unmodifiable list of top-level services declared in this file. + + + + + Unmodifiable list of top-level extensions declared in this file. + Note that some extensions may be incomplete (FieldDescriptor.Extension may be null) + if this descriptor was generated using a version of protoc that did not fully + support extensions in C#. + + + + + Unmodifiable list of this file's dependencies (imports). + + + + + Unmodifiable list of this file's public dependencies (public imports). + + + + + The original serialized binary form of this descriptor. + + + + + Implementation of IDescriptor.FullName - just returns the same as Name. + + + + + Implementation of IDescriptor.File - just returns this descriptor. + + + + + Pool containing symbol descriptors. + + + + + Finds a type (message, enum, service or extension) in the file by name. Does not find nested types. + + The unqualified type name to look for. + The type of descriptor to look for + The type's descriptor, or null if not found. + + + + Builds a FileDescriptor from its protocol buffer representation. + + The original serialized descriptor data. + We have only limited proto2 support, so serializing FileDescriptorProto + would not necessarily give us this. + The protocol message form of the FileDescriptor. + FileDescriptors corresponding to all of the + file's dependencies, in the exact order listed in the .proto file. May be null, + in which case it is treated as an empty array. + Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false). + Details about generated code, for the purposes of reflection. + If is not + a valid descriptor. This can occur for a number of reasons, such as a field + having an undefined type or because two messages were defined with the same name. + + + + Creates a descriptor for generated code. + + + This method is only designed to be used by the results of generating code with protoc, + which creates the appropriate dependencies etc. It has to be public because the generated + code is "external", but should not be called directly by end users. + + + + + Converts the given descriptor binary data into FileDescriptor objects. + Note: reflection using the returned FileDescriptors is not currently supported. + + The binary file descriptor proto data. Must not be null, and any + dependencies must come before the descriptor which depends on them. (If A depends on B, and B + depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible + with the order in which protoc provides descriptors to plugins. + The extension registry to use when parsing, or null if no extensions are required. + The file descriptors corresponding to . + + + + Converts the given descriptor binary data into FileDescriptor objects. + Note: reflection using the returned FileDescriptors is not currently supported. + + The binary file descriptor proto data. Must not be null, and any + dependencies must come before the descriptor which depends on them. (If A depends on B, and B + depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible + with the order in which protoc provides descriptors to plugins. + The file descriptors corresponding to . + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns the file descriptor for descriptor.proto. + + + This is used for protos which take a direct dependency on descriptor.proto, typically for + annotations. While descriptor.proto is a proto2 file, it is built into the Google.Protobuf + runtime for reflection purposes. The messages are internal to the runtime as they would require + proto2 semantics for full support, but the file descriptor is available via this property. The + C# codegen in protoc automatically uses this property when it detects a dependency on descriptor.proto. + + + The file descriptor for descriptor.proto. + + + + + The (possibly empty) set of custom options for this file. + + + + + The FileOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value file option for this descriptor + + + + + Gets a repeated value file option for this descriptor + + + + + Performs initialization for the given generic type argument. + + + This method is present for the sake of AOT compilers. It allows code (whether handwritten or generated) + to make calls into the reflection machinery of this library to express an intention to use that type + reflectively (e.g. for JSON parsing and formatting). The call itself does almost nothing, but AOT compilers + attempting to determine which generic type arguments need to be handled will spot the code path and act + accordingly. + + The type to force initialization for. + + + + Extra information provided by generated code when initializing a message or file descriptor. + These are constructed as required, and are not long-lived. Hand-written code should + never need to use this type. + + + + + Irrelevant for file descriptors; the CLR type for the message for message descriptors. + + + + + Irrelevant for file descriptors; the parser for message descriptors. + + + + + Irrelevant for file descriptors; the CLR property names (in message descriptor field order) + for fields in the message for message descriptors. + + + + + The extensions defined within this file/message descriptor + + + + + Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order) + for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo", + there will be a "FooCase" property and a "ClearFoo" method. + + + + + The reflection information for types within this file/message descriptor. Elements may be null + if there is no corresponding generated type, e.g. for map entry types. + + + + + The CLR types for enums within this file/message descriptor. + + + + + Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. + Each array parameter may be null, to indicate a lack of values. + The parameter order is designed to make it feasible to format the generated code readably. + + + + + Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. + Each array parameter may be null, to indicate a lack of values. + The parameter order is designed to make it feasible to format the generated code readably. + + + + + Creates a GeneratedClrTypeInfo for a file descriptor, with only types, enums, and extensions. + + + + + Creates a GeneratedClrTypeInfo for a file descriptor, with only types and enums. + + + + + Interface implemented by all descriptor types. + + + + + Returns the name of the entity (message, field etc) being described. + + + + + Returns the fully-qualified name of the entity being described. + + + + + Returns the descriptor for the .proto file that this entity is part of. + + + + + Allows fields to be reflectively accessed. + + + + + Returns the descriptor associated with this field. + + + + + Clears the field in the specified message. (For repeated fields, + this clears the list.) + + + + + Fetches the field value. For repeated values, this will be an + implementation. For map values, this will be an + implementation. + + + + + Indicates whether the field in the specified message is set. + For proto3 fields that aren't explicitly optional, this throws an + + + + + Mutator for single "simple" fields only. + + + Repeated fields are mutated by fetching the value and manipulating it as a list. + Map fields are mutated by fetching the value and manipulating it as a dictionary. + + The field is not a "simple" field. + + + + Accessor for map fields. + + + + + Describes a message type. + + + + + The brief name of the descriptor's target. + + + + + Returns a clone of the underlying describing this message. + Note that a copy is taken every time this method is called, so clients using it frequently + (and not modifying it) may want to cache the returned value. + + A protobuf representation of this message descriptor. + + + + The CLR type used to represent message instances from this descriptor. + + + + The value returned by this property will be non-null for all regular fields. However, + if a message containing a map field is introspected, the list of nested messages will include + an auto-generated nested key/value pair message for the field. This is not represented in any + generated type, so this property will return null in such cases. + + + For wrapper types ( and the like), the type returned here + will be the generated message type, not the native type used by reflection for fields of those types. Code + using reflection should call to determine whether a message descriptor represents + a wrapper type, and handle the result appropriately. + + + + + + A parser for this message type. + + + + As is not generic, this cannot be statically + typed to the relevant type, but it should produce objects of a type compatible with . + + + The value returned by this property will be non-null for all regular fields. However, + if a message containing a map field is introspected, the list of nested messages will include + an auto-generated nested key/value pair message for the field. No message parser object is created for + such messages, so this property will return null in such cases. + + + For wrapper types ( and the like), the parser returned here + will be the generated message type, not the native type used by reflection for fields of those types. Code + using reflection should call to determine whether a message descriptor represents + a wrapper type, and handle the result appropriately. + + + + + + Returns whether this message is one of the "well known types" which may have runtime/protoc support. + + + + + Returns whether this message is one of the "wrapper types" used for fields which represent primitive values + with the addition of presence. + + + + + If this is a nested type, get the outer descriptor, otherwise null. + + + + + A collection of fields, which can be retrieved by name or field number. + + + + + An unmodifiable list of extensions defined in this message's scope. + Note that some extensions may be incomplete (FieldDescriptor.Extension may be null) + if they are declared in a file generated using a version of protoc that did not fully + support extensions in C#. + + + + + An unmodifiable list of this message type's nested types. + + + + + An unmodifiable list of this message type's enum types. + + + + + An unmodifiable list of the "oneof" field collections in this message type. + All "real" oneofs (where returns false) + come before synthetic ones. + + + + + The number of real "oneof" descriptors in this message type. Every element in + with an index less than this will have a property value + of false; every element with an index greater than or equal to this will have a + property value of true. + + + + + Finds a field by field name. + + The unqualified name of the field (e.g. "foo"). + The field's descriptor, or null if not found. + + + + Finds a field by field number. + + The field number within this message type. + The field's descriptor, or null if not found. + + + + Finds a nested descriptor by name. The is valid for fields, nested + message types, oneofs and enums. + + The unqualified name of the descriptor, e.g. "Foo" + The descriptor, or null if not found. + + + + The (possibly empty) set of custom options for this message. + + + + + The MessageOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value message option for this descriptor + + + + + Gets a repeated value message option for this descriptor + + + + + Looks up and cross-links all fields and nested types. + + + + + A collection to simplify retrieving the field accessor for a particular field. + + + + + Returns the fields in the message as an immutable list, in the order in which they + are declared in the source .proto file. + + + + + Returns the fields in the message as an immutable list, in ascending field number + order. Field numbers need not be contiguous, so there is no direct mapping from the + index in the list to the field number; to retrieve a field by field number, it is better + to use the indexer. + + + + + Returns a read-only dictionary mapping the field names in this message as they're available + in the JSON representation to the field descriptors. For example, a field foo_bar + in the message would result two entries, one with a key fooBar and one with a key + foo_bar, both referring to the same field. + + + + + Retrieves the descriptor for the field with the given number. + + Number of the field to retrieve the descriptor for + The accessor for the given field + The message descriptor does not contain a field + with the given number + + + + Retrieves the descriptor for the field with the given name. + + Name of the field to retrieve the descriptor for + The descriptor for the given field + The message descriptor does not contain a field + with the given name + + + + Describes a single method in a service. + + + + + The service this method belongs to. + + + + + The method's input type. + + + + + The method's input type. + + + + + Indicates if client streams multiple requests. + + + + + Indicates if server streams multiple responses. + + + + + The (possibly empty) set of custom options for this method. + + + + + The MethodOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value method option for this descriptor + + + + + Gets a repeated value method option for this descriptor + + + + + Returns a clone of the underlying describing this method. + Note that a copy is taken every time this method is called, so clients using it frequently + (and not modifying it) may want to cache the returned value. + + A protobuf representation of this method descriptor. + + + + The brief name of the descriptor's target. + + + + + Reflection access for a oneof, allowing clear and "get case" actions. + + + + + Gets the descriptor for this oneof. + + + The descriptor of the oneof. + + + + + Clears the oneof in the specified message. + + + + + Indicates which field in the oneof is set for specified message + + + + + Describes a "oneof" field collection in a message type: a set of + fields of which at most one can be set in any particular message. + + + + + The brief name of the descriptor's target. + + + + + Returns a clone of the underlying describing this oneof. + Note that a copy is taken every time this method is called, so clients using it frequently + (and not modifying it) may want to cache the returned value. + + A protobuf representation of this oneof descriptor. + + + + Gets the message type containing this oneof. + + + The message type containing this oneof. + + + + + Gets the fields within this oneof, in declaration order. + + + The fields within this oneof, in declaration order. + + + + + Returns true if this oneof is a synthetic oneof containing a proto3 optional field; + false otherwise. + + + + + Gets an accessor for reflective access to the values associated with the oneof + in a particular message. + + + + In descriptors for generated code, the value returned by this property will always be non-null. + + + In dynamically loaded descriptors, the value returned by this property will current be null; + if and when dynamic messages are supported, it will return a suitable accessor to work with + them. + + + + The accessor used for reflective access. + + + + + The (possibly empty) set of custom options for this oneof. + + + + + The OneofOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value oneof option for this descriptor + + + + + Gets a repeated value oneof option for this descriptor + + + + + Specifies the original name (in the .proto file) of a named element, + such as an enum value. + + + + + The name of the element in the .proto file. + + + + + If the name is preferred in the .proto file. + + + + + Constructs a new attribute instance for the given name. + + The name of the element in the .proto file. + + + + Represents a package in the symbol table. We use PackageDescriptors + just as placeholders so that someone cannot define, say, a message type + that has the same name as an existing package. + + + + + The methods in this class are somewhat evil, and should not be tampered with lightly. + Basically they allow the creation of relatively weakly typed delegates from MethodInfos + which are more strongly typed. They do this by creating an appropriate strongly typed + delegate from the MethodInfo, and then calling that within an anonymous method. + Mind-bending stuff (at least to your humble narrator) but the resulting delegates are + very fast compared with calling Invoke later on. + + + + + Empty Type[] used when calling GetProperty to force property instead of indexer fetching. + + + + + Creates a delegate which will cast the argument to the type that declares the method, + call the method on it, then convert the result to object. + + The method to create a delegate for, which must be declared in an IMessage + implementation. + + + + Creates a delegate which will cast the argument to the type that declares the method, + call the method on it, then convert the result to the specified type. The method is expected + to actually return an enum (because of where we're calling it - for oneof cases). Sometimes that + means we need some extra work to perform conversions. + + The method to create a delegate for, which must be declared in an IMessage + implementation. + + + + Creates a delegate which will execute the given method after casting the first argument to + the type that declares the method, and the second argument to the first parameter type of the method. + + The method to create a delegate for, which must be declared in an IMessage + implementation. + + + + Creates a delegate which will execute the given method after casting the first argument to + type that declares the method. + + The method to create a delegate for, which must be declared in an IMessage + implementation. + + + + Creates a delegate which will execute the given method after casting the first argument to + the type that declares the method, and the second argument to the first parameter type of the method. + + + + + Creates a reflection helper for the given type arguments. Currently these are created on demand + rather than cached; this will be "busy" when initially loading a message's descriptor, but after that + they can be garbage collected. We could cache them by type if that proves to be important, but creating + an object is pretty cheap. + + + + + Accessor for repeated fields. + + + + + Describes a service type. + + + + + The brief name of the descriptor's target. + + + + + Returns a clone of the underlying describing this service. + Note that a copy is taken every time this method is called, so clients using it frequently + (and not modifying it) may want to cache the returned value. + + A protobuf representation of this service descriptor. + + + + An unmodifiable list of methods in this service. + + + + + Finds a method by name. + + The unqualified name of the method (e.g. "Foo"). + The method's descriptor, or null if not found. + + + + The (possibly empty) set of custom options for this service. + + + + + The ServiceOptions, defined in descriptor.proto. + If the options message is not present (i.e. there are no options), null is returned. + Custom options can be retrieved as extensions of the returned message. + NOTE: A defensive copy is created each time this property is retrieved. + + + + + Gets a single value service option for this descriptor + + + + + Gets a repeated value service option for this descriptor + + + + + Accessor for single fields. + + + + + An immutable registry of types which can be looked up by their full name. + + + + + An empty type registry, containing no types. + + + + + Attempts to find a message descriptor by its full name. + + The full name of the message, which is the dot-separated + combination of package, containing messages and message name + The message descriptor corresponding to or null + if there is no such message descriptor. + + + + Creates a type registry from the specified set of file descriptors. + + + This is a convenience overload for + to allow calls such as TypeRegistry.FromFiles(descriptor1, descriptor2). + + The set of files to include in the registry. Must not contain null values. + A type registry for the given files. + + + + Creates a type registry from the specified set of file descriptors. + + + All message types within all the specified files are added to the registry, and + the dependencies of the specified files are also added, recursively. + + The set of files to include in the registry. Must not contain null values. + A type registry for the given files. + + + + Creates a type registry from the file descriptor parents of the specified set of message descriptors. + + + This is a convenience overload for + to allow calls such as TypeRegistry.FromFiles(descriptor1, descriptor2). + + The set of message descriptors to use to identify file descriptors to include in the registry. + Must not contain null values. + A type registry for the given files. + + + + Creates a type registry from the file descriptor parents of the specified set of message descriptors. + + + The specified message descriptors are only used to identify their file descriptors; the returned registry + contains all the types within the file descriptors which contain the specified message descriptors (and + the dependencies of those files), not just the specified messages. + + The set of message descriptors to use to identify file descriptors to include in the registry. + Must not contain null values. + A type registry for the given files. + + + + Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls. + + + + + Abstraction for reading from a stream / read only sequence. + Parsing from the buffer is a loop of reading from current buffer / refreshing the buffer once done. + + + + + Initialize an instance with a coded input stream. + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Initialize an instance with a read only sequence. + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Sets currentLimit to (current position) + byteLimit. This is called + when descending into a length-delimited embedded message. The previous + limit is returned. + + The old limit. + + + + Discards the current limit, returning the previous limit. + + + + + Returns whether or not all the data before the limit has been read. + + + + + + Returns true if the stream has reached the end of the input. This is the + case if either the end of the underlying input source has been reached or + the stream has reached a limit created using PushLimit. + + + + + Represents a single field in an UnknownFieldSet. + + An UnknownField consists of four lists of values. The lists correspond + to the four "wire types" used in the protocol buffer binary format. + Normally, only one of the four lists will contain any values, since it + is impossible to define a valid message type that declares two different + types for the same field number. However, the code is designed to allow + for the case where the same unknown field number is encountered using + multiple different wire types. + + + + + + Creates a new UnknownField. + + + + + Checks if two unknown field are equal. + + + + + Get the hash code of the unknown field. + + + + + Serializes the field, including the field number, and writes it to + + + The unknown field number. + The write context to write to. + + + + Computes the number of bytes required to encode this field, including field + number. + + + + + Merge the values in into this field. For each list + of values, 's values are append to the ones in this + field. + + + + + Returns a new list containing all of the given specified values from + both the and lists. + If is null and is null or empty, + null is returned. Otherwise, either a new list is created (if + is null) or the elements of are added to . + + + + + Adds a varint value. + + + + + Adds a fixed32 value. + + + + + Adds a fixed64 value. + + + + + Adds a length-delimited value. + + + + + Adds to the , creating + a new list if is null. The list is returned - either + the original reference or the new list. + + + + + Used to keep track of fields which were seen when parsing a protocol message + but whose field numbers or types are unrecognized. This most frequently + occurs when new fields are added to a message type and then messages containing + those fields are read by old software that was built before the new types were + added. + + Most users will never need to use this class directly. + + + + + Creates a new UnknownFieldSet. + + + + + Checks whether or not the given field number is present in the set. + + + + + Serializes the set and writes it to . + + + + + Serializes the set and writes it to . + + + + + Gets the number of bytes required to encode this set. + + + + + Checks if two unknown field sets are equal. + + + + + Gets the unknown field set's hash code. + + + + + Adds a field to the set. If a field with the same number already exists, it + is replaced. + + + + + Parse a single field from and merge it + into this set. + + The parse context from which to read the field + false if the tag is an "end group" tag, true otherwise + + + + Create a new UnknownFieldSet if unknownFields is null. + Parse a single field from and merge it + into unknownFields. If is configured to discard unknown fields, + will be returned as-is and the field will be skipped. + + The UnknownFieldSet which need to be merged + The coded input stream containing the field + The merged UnknownFieldSet + + + + Create a new UnknownFieldSet if unknownFields is null. + Parse a single field from and merge it + into unknownFields. If is configured to discard unknown fields, + will be returned as-is and the field will be skipped. + + The UnknownFieldSet which need to be merged + The parse context from which to read the field + The merged UnknownFieldSet + + + + Merges the fields from into this set. + If a field number exists in both sets, the values in + will be appended to the values in this set. + + + + + Created a new UnknownFieldSet to if + needed and merges the fields from into the first set. + If a field number exists in both sets, the values in + will be appended to the values in this set. + + + + + Adds a field to the unknown field set. If a field with the same + number already exists, the two are merged. + + + + + Clone an unknown field set from . + + + + + Provides a number of unsafe byte operations to be used by advanced applications with high performance + requirements. These methods are referred to as "unsafe" due to the fact that they potentially expose + the backing buffer of a to the application. + + + + The methods in this class should only be called if it is guaranteed that the buffer backing the + will never change! Mutation of a can lead to unexpected + and undesirable consequences in your application, and will likely be difficult to debug. Proceed with caution! + + + This can have a number of significant side affects that have spooky-action-at-a-distance-like behavior. In + particular, if the bytes value changes out from under a Protocol Buffer: + + + + serialization may throw + + + serialization may succeed but the wrong bytes may be written out + + + objects that are normally immutable (such as ByteString) are no longer immutable + + + hashCode may be incorrect + + + + + + + Constructs a new from the given bytes. The bytes are not copied, + and must not be modified while the is in use. + This API is experimental and subject to change. + + + + Holder for reflection information generated from google/protobuf/any.proto + + + File descriptor for google/protobuf/any.proto + + + + `Any` contains an arbitrary serialized protocol buffer message along with a + URL that describes the type of the serialized message. + + Protobuf library provides support to pack/unpack Any values in the form + of utility functions or additional generated methods of the Any type. + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := anypb.New(foo) + if err != nil { + ... + } + ... + foo := &pb.Foo{} + if err := any.UnmarshalTo(foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + 'type.googleapis.com/full.type.name' as the type URL and the unpack + methods only use the fully qualified type name after the last '/' + in the type URL, for example "foo.bar.com/x/y.z" will yield type + name "y.z". + + JSON + + The JSON representation of an `Any` value uses the regular + representation of the deserialized, embedded message, with an + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": <string>, + "lastName": <string> + } + + If the embedded message type is well-known and has a custom JSON + representation, that representation will be embedded adding a field + `value` which holds the custom JSON in addition to the `@type` + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + + + + Field number for the "type_url" field. + + + + A URL/resource name that uniquely identifies the type of the serialized + protocol buffer message. This string must contain at least + one "/" character. The last segment of the URL's path must represent + the fully qualified name of the type (as in + `path/google.protobuf.Duration`). The name should be in a canonical form + (e.g., leading "." is not accepted). + + In practice, teams usually precompile into the binary all types that they + expect it to use in the context of Any. However, for URLs which use the + scheme `http`, `https`, or no scheme, one can optionally set up a type + server that maps type URLs to message definitions as follows: + + * If no scheme is provided, `https` is assumed. + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the official + protobuf release, and it is not used for type URLs beginning with + type.googleapis.com. + + Schemes other than `http`, `https` (or the empty scheme) might be + used with implementation specific semantics. + + + + Field number for the "value" field. + + + + Must be a valid serialized protocol buffer of the above specified type. + + + + + Retrieves the type name for a type URL, matching the + of the packed message type. + + + + This is always just the last part of the URL, after the final slash. No validation of + anything before the trailing slash is performed. If the type URL does not include a slash, + an empty string is returned rather than an exception being thrown; this won't match any types, + and the calling code is probably in a better position to give a meaningful error. + + + There is no handling of fragments or queries at the moment. + + + The URL to extract the type name from + The type name + + + + Returns a bool indictating whether this Any message is of the target message type + + The descriptor of the message type + true if the type name matches the descriptor's full name or false otherwise + + + + Unpacks the content of this Any message into the target message type, + which must match the type URL within this Any message. + + The type of message to unpack the content into. + The unpacked message. + The target message type doesn't match the type URL in this message + + + + Attempts to unpack the content of this Any message into the target message type, + if it matches the type URL within this Any message. + + The type of message to attempt to unpack the content into. + true if the message was successfully unpacked; false if the type name didn't match + + + + Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com". + + The message to pack. + An Any message with the content and type URL of . + + + + Packs the specified message into an Any message using the specified type URL prefix. + + The message to pack. + The prefix for the type URL. + An Any message with the content and type URL of . + + + Holder for reflection information generated from google/protobuf/api.proto + + + File descriptor for google/protobuf/api.proto + + + + Api is a light-weight descriptor for an API Interface. + + Interfaces are also described as "protocol buffer services" in some contexts, + such as by the "service" keyword in a .proto file, but they are different + from API Services, which represent a concrete implementation of an interface + as opposed to simply a description of methods and bindings. They are also + sometimes simply referred to as "APIs" in other contexts, such as the name of + this message itself. See https://cloud.google.com/apis/design/glossary for + detailed terminology. + + + + Field number for the "name" field. + + + + The fully qualified name of this interface, including package name + followed by the interface's simple name. + + + + Field number for the "methods" field. + + + + The methods of this interface, in unspecified order. + + + + Field number for the "options" field. + + + + Any metadata attached to the interface. + + + + Field number for the "version" field. + + + + A version string for this interface. If specified, must have the form + `major-version.minor-version`, as in `1.10`. If the minor version is + omitted, it defaults to zero. If the entire version field is empty, the + major version is derived from the package name, as outlined below. If the + field is not empty, the version in the package name will be verified to be + consistent with what is provided here. + + The versioning schema uses [semantic + versioning](http://semver.org) where the major version number + indicates a breaking change and the minor version an additive, + non-breaking change. Both version numbers are signals to users + what to expect from different versions, and should be carefully + chosen based on the product plan. + + The major version is also reflected in the package name of the + interface, which must end in `v<major-version>`, as in + `google.feature.v1`. For major versions 0 and 1, the suffix can + be omitted. Zero major versions must only be used for + experimental, non-GA interfaces. + + + + Field number for the "source_context" field. + + + + Source context for the protocol buffer service represented by this + message. + + + + Field number for the "mixins" field. + + + + Included interfaces. See [Mixin][]. + + + + Field number for the "syntax" field. + + + + The source syntax of the service. + + + + + Method represents a method of an API interface. + + + + Field number for the "name" field. + + + + The simple name of this method. + + + + Field number for the "request_type_url" field. + + + + A URL of the input message type. + + + + Field number for the "request_streaming" field. + + + + If true, the request is streamed. + + + + Field number for the "response_type_url" field. + + + + The URL of the output message type. + + + + Field number for the "response_streaming" field. + + + + If true, the response is streamed. + + + + Field number for the "options" field. + + + + Any metadata attached to the method. + + + + Field number for the "syntax" field. + + + + The source syntax of this method. + + + + + Declares an API Interface to be included in this interface. The including + interface must redeclare all the methods from the included interface, but + documentation and options are inherited as follows: + + - If after comment and whitespace stripping, the documentation + string of the redeclared method is empty, it will be inherited + from the original method. + + - Each annotation belonging to the service config (http, + visibility) which is not set in the redeclared method will be + inherited. + + - If an http annotation is inherited, the path pattern will be + modified as follows. Any version prefix will be replaced by the + version of the including interface plus the [root][] path if + specified. + + Example of a simple mixin: + + package google.acl.v1; + service AccessControl { + // Get the underlying ACL object. + rpc GetAcl(GetAclRequest) returns (Acl) { + option (google.api.http).get = "/v1/{resource=**}:getAcl"; + } + } + + package google.storage.v2; + service Storage { + rpc GetAcl(GetAclRequest) returns (Acl); + + // Get a data record. + rpc GetData(GetDataRequest) returns (Data) { + option (google.api.http).get = "/v2/{resource=**}"; + } + } + + Example of a mixin configuration: + + apis: + - name: google.storage.v2.Storage + mixins: + - name: google.acl.v1.AccessControl + + The mixin construct implies that all methods in `AccessControl` are + also declared with same name and request/response types in + `Storage`. A documentation generator or annotation processor will + see the effective `Storage.GetAcl` method after inheriting + documentation and annotations as follows: + + service Storage { + // Get the underlying ACL object. + rpc GetAcl(GetAclRequest) returns (Acl) { + option (google.api.http).get = "/v2/{resource=**}:getAcl"; + } + ... + } + + Note how the version in the path pattern changed from `v1` to `v2`. + + If the `root` field in the mixin is specified, it should be a + relative path under which inherited HTTP paths are placed. Example: + + apis: + - name: google.storage.v2.Storage + mixins: + - name: google.acl.v1.AccessControl + root: acls + + This implies the following inherited HTTP annotation: + + service Storage { + // Get the underlying ACL object. + rpc GetAcl(GetAclRequest) returns (Acl) { + option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; + } + ... + } + + + + Field number for the "name" field. + + + + The fully qualified name of the interface which is included. + + + + Field number for the "root" field. + + + + If non-empty specifies a path under which inherited HTTP paths + are rooted. + + + + Holder for reflection information generated from google/protobuf/duration.proto + + + File descriptor for google/protobuf/duration.proto + + + + A Duration represents a signed, fixed-length span of time represented + as a count of seconds and fractions of seconds at nanosecond + resolution. It is independent of any calendar and concepts like "day" + or "month". It is related to Timestamp in that the difference between + two Timestamp values is a Duration and it can be added or subtracted + from a Timestamp. Range is approximately +-10,000 years. + + # Examples + + Example 1: Compute Duration from two Timestamps in pseudo code. + + Timestamp start = ...; + Timestamp end = ...; + Duration duration = ...; + + duration.seconds = end.seconds - start.seconds; + duration.nanos = end.nanos - start.nanos; + + if (duration.seconds < 0 && duration.nanos > 0) { + duration.seconds += 1; + duration.nanos -= 1000000000; + } else if (duration.seconds > 0 && duration.nanos < 0) { + duration.seconds -= 1; + duration.nanos += 1000000000; + } + + Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + + Timestamp start = ...; + Duration duration = ...; + Timestamp end = ...; + + end.seconds = start.seconds + duration.seconds; + end.nanos = start.nanos + duration.nanos; + + if (end.nanos < 0) { + end.seconds -= 1; + end.nanos += 1000000000; + } else if (end.nanos >= 1000000000) { + end.seconds += 1; + end.nanos -= 1000000000; + } + + Example 3: Compute Duration from datetime.timedelta in Python. + + td = datetime.timedelta(days=3, minutes=10) + duration = Duration() + duration.FromTimedelta(td) + + # JSON Mapping + + In JSON format, the Duration type is encoded as a string rather than an + object, where the string ends in the suffix "s" (indicating seconds) and + is preceded by the number of seconds, with nanoseconds expressed as + fractional seconds. For example, 3 seconds with 0 nanoseconds should be + encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + microsecond should be expressed in JSON format as "3.000001s". + + + + Field number for the "seconds" field. + + + + Signed seconds of the span of time. Must be from -315,576,000,000 + to +315,576,000,000 inclusive. Note: these bounds are computed from: + 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + + + + Field number for the "nanos" field. + + + + Signed fractions of a second at nanosecond resolution of the span + of time. Durations less than one second are represented with a 0 + `seconds` field and a positive or negative `nanos` field. For durations + of one second or more, a non-zero value for the `nanos` field must be + of the same sign as the `seconds` field. Must be from -999,999,999 + to +999,999,999 inclusive. + + + + + The number of nanoseconds in a second. + + + + + The number of nanoseconds in a BCL tick (as used by and ). + + + + + The maximum permitted number of seconds. + + + + + The minimum permitted number of seconds. + + + + + Converts this to a . + + If the duration is not a precise number of ticks, it is truncated towards 0. + The value of this duration, as a TimeSpan. + This value isn't a valid normalized duration, as + described in the documentation. + + + + Converts the given to a . + + The TimeSpan to convert. + The value of the given TimeSpan, as a Duration. + + + + Returns the result of negating the duration. For example, the negation of 5 minutes is -5 minutes. + + The duration to negate. Must not be null. + The negated value of this duration. + + + + Adds the two specified values together. + + The first value to add. Must not be null. + The second value to add. Must not be null. + + + + + Subtracts one from another. + + The duration to subtract from. Must not be null. + The duration to subtract. Must not be null. + The difference between the two specified durations. + + + + Creates a duration with the normalized values from the given number of seconds and + nanoseconds, conforming with the description in the proto file. + + + + + Converts a duration specified in seconds/nanoseconds to a string. + + + If the value is a normalized duration in the range described in duration.proto, + is ignored. Otherwise, if the parameter is true, + a JSON object with a warning is returned; if it is false, an is thrown. + + Seconds portion of the duration. + Nanoseconds portion of the duration. + Determines the handling of non-normalized values + The represented duration is invalid, and is false. + + + + Returns a string representation of this for diagnostic purposes. + + + Normally the returned value will be a JSON string value (including leading and trailing quotes) but + when the value is non-normalized or out of range, a JSON object representation will be returned + instead, including a warning. This is to avoid exceptions being thrown when trying to + diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + values. + + A string representation of this value. + + + + Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which + case no "." is appended), or 3 6 or 9 digits. This is internal for use in Timestamp as well + as Duration. + + + + Holder for reflection information generated from google/protobuf/empty.proto + + + File descriptor for google/protobuf/empty.proto + + + + A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to use it as the request + or the response type of an API method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); + } + + + + Holder for reflection information generated from google/protobuf/field_mask.proto + + + File descriptor for google/protobuf/field_mask.proto + + + + `FieldMask` represents a set of symbolic field paths, for example: + + paths: "f.a" + paths: "f.b.d" + + Here `f` represents a field in some root message, `a` and `b` + fields in the message found in `f`, and `d` a field found in the + message in `f.b`. + + Field masks are used to specify a subset of fields that should be + returned by a get operation or modified by an update operation. + Field masks also have a custom JSON encoding (see below). + + # Field Masks in Projections + + When used in the context of a projection, a response message or + sub-message is filtered by the API to only contain those fields as + specified in the mask. For example, if the mask in the previous + example is applied to a response message as follows: + + f { + a : 22 + b { + d : 1 + x : 2 + } + y : 13 + } + z: 8 + + The result will not contain specific values for fields x,y and z + (their value will be set to the default, and omitted in proto text + output): + + f { + a : 22 + b { + d : 1 + } + } + + A repeated field is not allowed except at the last position of a + paths string. + + If a FieldMask object is not present in a get operation, the + operation applies to all fields (as if a FieldMask of all fields + had been specified). + + Note that a field mask does not necessarily apply to the + top-level response message. In case of a REST get operation, the + field mask applies directly to the response, but in case of a REST + list operation, the mask instead applies to each individual message + in the returned resource list. In case of a REST custom method, + other definitions may be used. Where the mask applies will be + clearly documented together with its declaration in the API. In + any case, the effect on the returned resource/resources is required + behavior for APIs. + + # Field Masks in Update Operations + + A field mask in update operations specifies which fields of the + targeted resource are going to be updated. The API is required + to only change the values of the fields as specified in the mask + and leave the others untouched. If a resource is passed in to + describe the updated values, the API ignores the values of all + fields not covered by the mask. + + If a repeated field is specified for an update operation, new values will + be appended to the existing repeated field in the target resource. Note that + a repeated field is only allowed in the last position of a `paths` string. + + If a sub-message is specified in the last position of the field mask for an + update operation, then new value will be merged into the existing sub-message + in the target resource. + + For example, given the target message: + + f { + b { + d: 1 + x: 2 + } + c: [1] + } + + And an update message: + + f { + b { + d: 10 + } + c: [2] + } + + then if the field mask is: + + paths: ["f.b", "f.c"] + + then the result will be: + + f { + b { + d: 10 + x: 2 + } + c: [1, 2] + } + + An implementation may provide options to override this default behavior for + repeated and message fields. + + In order to reset a field's value to the default, the field must + be in the mask and set to the default value in the provided resource. + Hence, in order to reset all fields of a resource, provide a default + instance of the resource and set all fields in the mask, or do + not provide a mask as described below. + + If a field mask is not present on update, the operation applies to + all fields (as if a field mask of all fields has been specified). + Note that in the presence of schema evolution, this may mean that + fields the client does not know and has therefore not filled into + the request will be reset to their default. If this is unwanted + behavior, a specific service may require a client to always specify + a field mask, producing an error if not. + + As with get operations, the location of the resource which + describes the updated values in the request message depends on the + operation kind. In any case, the effect of the field mask is + required to be honored by the API. + + ## Considerations for HTTP REST + + The HTTP kind of an update operation which uses a field mask must + be set to PATCH instead of PUT in order to satisfy HTTP semantics + (PUT must only be used for full updates). + + # JSON Encoding of Field Masks + + In JSON, a field mask is encoded as a single string where paths are + separated by a comma. Fields name in each path are converted + to/from lower-camel naming conventions. + + As an example, consider the following message declarations: + + message Profile { + User user = 1; + Photo photo = 2; + } + message User { + string display_name = 1; + string address = 2; + } + + In proto a field mask for `Profile` may look as such: + + mask { + paths: "user.display_name" + paths: "photo" + } + + In JSON, the same mask is represented as below: + + { + mask: "user.displayName,photo" + } + + # Field Masks and Oneof Fields + + Field masks treat fields in oneofs just as regular fields. Consider the + following message: + + message SampleMessage { + oneof test_oneof { + string name = 4; + SubMessage sub_message = 9; + } + } + + The field mask can be: + + mask { + paths: "name" + } + + Or: + + mask { + paths: "sub_message" + } + + Note that oneof type names ("test_oneof" in this case) cannot be used in + paths. + + ## Field Mask Verification + + The implementation of any API method which has a FieldMask type field in the + request should verify the included field paths, and return an + `INVALID_ARGUMENT` error if any path is unmappable. + + + + Field number for the "paths" field. + + + + The set of field mask paths. + + + + + Converts a field mask specified by paths to a string. + + + If the value is a normalized duration in the range described in field_mask.proto, + is ignored. Otherwise, if the parameter is true, + a JSON object with a warning is returned; if it is false, an is thrown. + + Paths in the field mask + Determines the handling of non-normalized values + The represented field mask is invalid, and is false. + + + + Returns a string representation of this for diagnostic purposes. + + + Normally the returned value will be a JSON string value (including leading and trailing quotes) but + when the value is non-normalized or out of range, a JSON object representation will be returned + instead, including a warning. This is to avoid exceptions being thrown when trying to + diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + values. + + A string representation of this value. + + + + Parses from a string to a FieldMask. + + + + + Parses from a string to a FieldMask and validates all field paths. + + The type to validate the field paths against. + + + + Constructs a FieldMask for a list of field paths in a certain type. + + The type to validate the field paths against. + + + + Constructs a FieldMask from the passed field numbers. + + The type to validate the field paths against. + + + + Constructs a FieldMask from the passed field numbers. + + The type to validate the field paths against. + + + + Checks whether the given path is valid for a field mask. + + true if the path is valid; false otherwise + + + + Checks whether paths in a given fields mask are valid. + + The type to validate the field paths against. + + + + Checks whether paths in a given fields mask are valid. + + + + + Checks whether a given field path is valid. + + The type to validate the field paths against. + + + + Checks whether paths in a given fields mask are valid. + + + + + Converts this FieldMask to its canonical form. In the canonical form of a + FieldMask, all field paths are sorted alphabetically and redundant field + paths are removed. + + + + + Creates a union of two or more FieldMasks. + + + + + Calculates the intersection of two FieldMasks. + + + + + Merges fields specified by this FieldMask from one message to another with the + specified merge options. + + + + + Merges fields specified by this FieldMask from one message to another. + + + + + Options to customize merging behavior. + + + + + Whether to replace message fields(i.e., discard existing content in + destination message fields) when merging. + Default behavior is to merge the source message field into the + destination message field. + + + + + Whether to replace repeated fields (i.e., discard existing content in + destination repeated fields) when merging. + Default behavior is to append elements from source repeated field to the + destination repeated field. + + + + + Whether to replace primitive (non-repeated and non-message) fields in + destination message fields with the source primitive fields (i.e., if the + field is set in the source, the value is copied to the + destination; if the field is unset in the source, the field is cleared + from the destination) when merging. + + Default behavior is to always set the value of the source primitive + field to the destination primitive field, and if the source field is + unset, the default value of the source field is copied to the + destination. + + + + Holder for reflection information generated from google/protobuf/source_context.proto + + + File descriptor for google/protobuf/source_context.proto + + + + `SourceContext` represents information about the source of a + protobuf element, like the file in which it is defined. + + + + Field number for the "file_name" field. + + + + The path-qualified name of the .proto file that contained the associated + protobuf element. For example: `"google/protobuf/source_context.proto"`. + + + + Holder for reflection information generated from google/protobuf/struct.proto + + + File descriptor for google/protobuf/struct.proto + + + + `NullValue` is a singleton enumeration to represent the null value for the + `Value` type union. + + The JSON representation for `NullValue` is JSON `null`. + + + + + Null value. + + + + + `Struct` represents a structured data value, consisting of fields + which map to dynamically typed values. In some languages, `Struct` + might be supported by a native representation. For example, in + scripting languages like JS a struct is represented as an + object. The details of that representation are described together + with the proto support for the language. + + The JSON representation for `Struct` is JSON object. + + + + Field number for the "fields" field. + + + + Unordered map of dynamically typed values. + + + + + `Value` represents a dynamically typed value which can be either + null, a number, a string, a boolean, a recursive struct value, or a + list of values. A producer of value is expected to set one of these + variants. Absence of any variant indicates an error. + + The JSON representation for `Value` is JSON value. + + + + Field number for the "null_value" field. + + + + Represents a null value. + + + + Field number for the "number_value" field. + + + + Represents a double value. + + + + Field number for the "string_value" field. + + + + Represents a string value. + + + + Field number for the "bool_value" field. + + + + Represents a boolean value. + + + + Field number for the "struct_value" field. + + + + Represents a structured value. + + + + Field number for the "list_value" field. + + + + Represents a repeated `Value`. + + + + Enum of possible cases for the "kind" oneof. + + + + Convenience method to create a Value message with a string value. + + Value to set for the StringValue property. + A newly-created Value message with the given value. + + + + Convenience method to create a Value message with a number value. + + Value to set for the NumberValue property. + A newly-created Value message with the given value. + + + + Convenience method to create a Value message with a Boolean value. + + Value to set for the BoolValue property. + A newly-created Value message with the given value. + + + + Convenience method to create a Value message with a null initial value. + + A newly-created Value message a null initial value. + + + + Convenience method to create a Value message with an initial list of values. + + The values provided are not cloned; the references are copied directly. + A newly-created Value message an initial list value. + + + + Convenience method to create a Value message with an initial struct value + + The value provided is not cloned; the reference is copied directly. + A newly-created Value message an initial struct value. + + + + `ListValue` is a wrapper around a repeated field of values. + + The JSON representation for `ListValue` is JSON array. + + + + Field number for the "values" field. + + + + Repeated field of dynamically typed values. + + + + + Extension methods on BCL time-related types, converting to protobuf types. + + + + + Converts the given to a . + + The date and time to convert to a timestamp. + The value has a other than Utc. + The converted timestamp. + + + + Converts the given to a + + The offset is taken into consideration when converting the value (so the same instant in time + is represented) but is not a separate part of the resulting value. In other words, there is no + roundtrip operation to retrieve the original DateTimeOffset. + The date and time (with UTC offset) to convert to a timestamp. + The converted timestamp. + + + + Converts the given to a . + + The time span to convert. + The converted duration. + + + Holder for reflection information generated from google/protobuf/timestamp.proto + + + File descriptor for google/protobuf/timestamp.proto + + + + A Timestamp represents a point in time independent of any time zone or local + calendar, encoded as a count of seconds and fractions of seconds at + nanosecond resolution. The count is relative to an epoch at UTC midnight on + January 1, 1970, in the proleptic Gregorian calendar which extends the + Gregorian calendar backwards to year one. + + All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + second table is needed for interpretation, using a [24-hour linear + smear](https://developers.google.com/time/smear). + + The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + restricting to that range, we ensure that we can convert to and from [RFC + 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + + # Examples + + Example 1: Compute Timestamp from POSIX `time()`. + + Timestamp timestamp; + timestamp.set_seconds(time(NULL)); + timestamp.set_nanos(0); + + Example 2: Compute Timestamp from POSIX `gettimeofday()`. + + struct timeval tv; + gettimeofday(&tv, NULL); + + Timestamp timestamp; + timestamp.set_seconds(tv.tv_sec); + timestamp.set_nanos(tv.tv_usec * 1000); + + Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + + // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + Timestamp timestamp; + timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + + Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + + long millis = System.currentTimeMillis(); + + Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + .setNanos((int) ((millis % 1000) * 1000000)).build(); + + Example 5: Compute Timestamp from Java `Instant.now()`. + + Instant now = Instant.now(); + + Timestamp timestamp = + Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + .setNanos(now.getNano()).build(); + + Example 6: Compute Timestamp from current time in Python. + + timestamp = Timestamp() + timestamp.GetCurrentTime() + + # JSON Mapping + + In JSON format, the Timestamp type is encoded as a string in the + [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + where {year} is always expressed using four digits while {month}, {day}, + {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + is required. A proto3 JSON serializer should always use UTC (as indicated by + "Z") when printing the Timestamp type and a proto3 JSON parser should be + able to accept both UTC and other timezones (as indicated by an offset). + + For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + 01:30 UTC on January 15, 2017. + + In JavaScript, one can convert a Date object to this format using the + standard + [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + method. In Python, a standard `datetime.datetime` object can be converted + to this format using + [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + the Joda Time's [`ISODateTimeFormat.dateTime()`]( + http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + ) to obtain a formatter capable of generating timestamps in this format. + + + + Field number for the "seconds" field. + + + + Represents seconds of UTC time since Unix epoch + 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + 9999-12-31T23:59:59Z inclusive. + + + + Field number for the "nanos" field. + + + + Non-negative fractions of a second at nanosecond resolution. Negative + second values with fractions must still have non-negative nanos values + that count forward in time. Must be from 0 to 999,999,999 + inclusive. + + + + + Returns the difference between one and another, as a . + + The timestamp to subtract from. Must not be null. + The timestamp to subtract. Must not be null. + The difference between the two specified timestamps. + + + + Adds a to a , to obtain another Timestamp. + + The timestamp to add the duration to. Must not be null. + The duration to add. Must not be null. + The result of adding the duration to the timestamp. + + + + Subtracts a from a , to obtain another Timestamp. + + The timestamp to subtract the duration from. Must not be null. + The duration to subtract. + The result of subtracting the duration from the timestamp. + + + + Converts this timestamp into a . + + + The resulting DateTime will always have a Kind of Utc. + If the timestamp is not a precise number of ticks, it will be truncated towards the start + of time. For example, a timestamp with a value of 99 will result in a + value precisely on a second. + + This timestamp as a DateTime. + The timestamp contains invalid values; either it is + incorrectly normalized or is outside the valid range. + + + + Converts this timestamp into a . + + + The resulting DateTimeOffset will always have an Offset of zero. + If the timestamp is not a precise number of ticks, it will be truncated towards the start + of time. For example, a timestamp with a value of 99 will result in a + value precisely on a second. + + This timestamp as a DateTimeOffset. + The timestamp contains invalid values; either it is + incorrectly normalized or is outside the valid range. + + + + Converts the specified to a . + + + The Kind of is not DateTimeKind.Utc. + The converted timestamp. + + + + Converts the given to a + + The offset is taken into consideration when converting the value (so the same instant in time + is represented) but is not a separate part of the resulting value. In other words, there is no + roundtrip operation to retrieve the original DateTimeOffset. + The date and time (with UTC offset) to convert to a timestamp. + The converted timestamp. + + + + Converts a timestamp specified in seconds/nanoseconds to a string. + + + If the value is a normalized duration in the range described in timestamp.proto, + is ignored. Otherwise, if the parameter is true, + a JSON object with a warning is returned; if it is false, an is thrown. + + Seconds portion of the duration. + Nanoseconds portion of the duration. + Determines the handling of non-normalized values + The represented duration is invalid, and is false. + + + + Given another timestamp, returns 0 if the timestamps are equivalent, -1 if this timestamp precedes the other, and 1 otherwise + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + Timestamp to compare + an integer indicating whether this timestamp precedes or follows the other + + + + Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if a precedes b + + + + Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if a follows b + + + + Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if a precedes b + + + + Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if a follows b + + + + Returns whether two timestamps are equivalent + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if the two timestamps refer to the same nanosecond + + + + Returns whether two timestamps differ + + + Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + + + + true if the two timestamps differ + + + + Returns a string representation of this for diagnostic purposes. + + + Normally the returned value will be a JSON string value (including leading and trailing quotes) but + when the value is non-normalized or out of range, a JSON object representation will be returned + instead, including a warning. This is to avoid exceptions being thrown when trying to + diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + values. + + A string representation of this value. + + + Holder for reflection information generated from google/protobuf/type.proto + + + File descriptor for google/protobuf/type.proto + + + + The syntax in which a protocol buffer element is defined. + + + + + Syntax `proto2`. + + + + + Syntax `proto3`. + + + + + A protocol buffer message type. + + + + Field number for the "name" field. + + + + The fully qualified message name. + + + + Field number for the "fields" field. + + + + The list of fields. + + + + Field number for the "oneofs" field. + + + + The list of types appearing in `oneof` definitions in this type. + + + + Field number for the "options" field. + + + + The protocol buffer options. + + + + Field number for the "source_context" field. + + + + The source context. + + + + Field number for the "syntax" field. + + + + The source syntax. + + + + + A single field of a message type. + + + + Field number for the "kind" field. + + + + The field type. + + + + Field number for the "cardinality" field. + + + + The field cardinality. + + + + Field number for the "number" field. + + + + The field number. + + + + Field number for the "name" field. + + + + The field name. + + + + Field number for the "type_url" field. + + + + The field type URL, without the scheme, for message or enumeration + types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + + + + Field number for the "oneof_index" field. + + + + The index of the field type in `Type.oneofs`, for message or enumeration + types. The first type has index 1; zero means the type is not in the list. + + + + Field number for the "packed" field. + + + + Whether to use alternative packed wire representation. + + + + Field number for the "options" field. + + + + The protocol buffer options. + + + + Field number for the "json_name" field. + + + + The field JSON name. + + + + Field number for the "default_value" field. + + + + The string value of the default value of this field. Proto2 syntax only. + + + + Container for nested types declared in the Field message type. + + + + Basic field types. + + + + + Field type unknown. + + + + + Field type double. + + + + + Field type float. + + + + + Field type int64. + + + + + Field type uint64. + + + + + Field type int32. + + + + + Field type fixed64. + + + + + Field type fixed32. + + + + + Field type bool. + + + + + Field type string. + + + + + Field type group. Proto2 syntax only, and deprecated. + + + + + Field type message. + + + + + Field type bytes. + + + + + Field type uint32. + + + + + Field type enum. + + + + + Field type sfixed32. + + + + + Field type sfixed64. + + + + + Field type sint32. + + + + + Field type sint64. + + + + + Whether a field is optional, required, or repeated. + + + + + For fields with unknown cardinality. + + + + + For optional fields. + + + + + For required fields. Proto2 syntax only. + + + + + For repeated fields. + + + + + Enum type definition. + + + + Field number for the "name" field. + + + + Enum type name. + + + + Field number for the "enumvalue" field. + + + + Enum value definitions. + + + + Field number for the "options" field. + + + + Protocol buffer options. + + + + Field number for the "source_context" field. + + + + The source context. + + + + Field number for the "syntax" field. + + + + The source syntax. + + + + + Enum value definition. + + + + Field number for the "name" field. + + + + Enum value name. + + + + Field number for the "number" field. + + + + Enum value number. + + + + Field number for the "options" field. + + + + Protocol buffer options. + + + + + A protocol buffer option, which can be attached to a message, field, + enumeration, etc. + + + + Field number for the "name" field. + + + + The option's name. For protobuf built-in options (options defined in + descriptor.proto), this is the short name. For example, `"map_entry"`. + For custom options, it should be the fully-qualified name. For example, + `"google.api.http"`. + + + + Field number for the "value" field. + + + + The option's value packed in an Any message. If the value is a primitive, + the corresponding wrapper type defined in google/protobuf/wrappers.proto + should be used. If the value is an enum, it should be stored as an int32 + value using the google.protobuf.Int32Value type. + + + + Holder for reflection information generated from google/protobuf/wrappers.proto + + + File descriptor for google/protobuf/wrappers.proto + + + + Field number for the single "value" field in all wrapper types. + + + + + Wrapper message for `double`. + + The JSON representation for `DoubleValue` is JSON number. + + + + Field number for the "value" field. + + + + The double value. + + + + + Wrapper message for `float`. + + The JSON representation for `FloatValue` is JSON number. + + + + Field number for the "value" field. + + + + The float value. + + + + + Wrapper message for `int64`. + + The JSON representation for `Int64Value` is JSON string. + + + + Field number for the "value" field. + + + + The int64 value. + + + + + Wrapper message for `uint64`. + + The JSON representation for `UInt64Value` is JSON string. + + + + Field number for the "value" field. + + + + The uint64 value. + + + + + Wrapper message for `int32`. + + The JSON representation for `Int32Value` is JSON number. + + + + Field number for the "value" field. + + + + The int32 value. + + + + + Wrapper message for `uint32`. + + The JSON representation for `UInt32Value` is JSON number. + + + + Field number for the "value" field. + + + + The uint32 value. + + + + + Wrapper message for `bool`. + + The JSON representation for `BoolValue` is JSON `true` and `false`. + + + + Field number for the "value" field. + + + + The bool value. + + + + + Wrapper message for `string`. + + The JSON representation for `StringValue` is JSON string. + + + + Field number for the "value" field. + + + + The string value. + + + + + Wrapper message for `bytes`. + + The JSON representation for `BytesValue` is JSON string. + + + + Field number for the "value" field. + + + + The bytes value. + + + + + This class is used internally by the Protocol Buffer Library and generated + message implementations. It is public only for the sake of those generated + messages. Others should not use this class directly. + + This class contains constants and helper functions useful for dealing with + the Protocol Buffer wire format. + + + + + + Wire types within protobuf encoding. + + + + + Variable-length integer. + + + + + A fixed-length 64-bit value. + + + + + A length-delimited value, i.e. a length followed by that many bytes of data. + + + + + A "start group" value + + + + + An "end group" value + + + + + A fixed-length 32-bit value. + + + + + Given a tag value, determines the wire type (lower 3 bits). + + + + + Given a tag value, determines the field number (the upper 29 bits). + + + + + Makes a tag value given a field number and wire type. + + + + + Abstraction for writing to a steam / IBufferWriter + + + + + Initialize an instance with a coded output stream. + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Initialize an instance with a buffer writer. + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Initialize an instance with a buffer represented by a single span (i.e. buffer cannot be refreshed) + This approach is faster than using a constructor because the instance to initialize is passed by reference + and we can write directly into it without copying. + + + + + Verifies that SpaceLeft returns zero. + + + + + If writing to a flat array, returns the space left in the array. Otherwise, + throws an InvalidOperationException. + + + + + An opaque struct that represents the current serialization state and is passed along + as the serialization proceeds. + All the public methods are intended to be invoked only by the generated code, + users should never invoke them directly. + + + + + Creates a WriteContext instance from CodedOutputStream. + WARNING: internally this copies the CodedOutputStream's state, so after done with the WriteContext, + the CodedOutputStream's state needs to be updated. + + + + + Writes a double field value, without a tag. + + The value to write + + + + Writes a float field value, without a tag. + + The value to write + + + + Writes a uint64 field value, without a tag. + + The value to write + + + + Writes an int64 field value, without a tag. + + The value to write + + + + Writes an int32 field value, without a tag. + + The value to write + + + + Writes a fixed64 field value, without a tag. + + The value to write + + + + Writes a fixed32 field value, without a tag. + + The value to write + + + + Writes a bool field value, without a tag. + + The value to write + + + + Writes a string field value, without a tag. + The data is length-prefixed. + + The value to write + + + + Writes a message, without a tag. + The data is length-prefixed. + + The value to write + + + + Writes a group, without a tag, to the stream. + + The value to write + + + + Write a byte string, without a tag, to the stream. + The data is length-prefixed. + + The value to write + + + + Writes a uint32 value, without a tag. + + The value to write + + + + Writes an enum value, without a tag. + + The value to write + + + + Writes an sfixed32 value, without a tag. + + The value to write. + + + + Writes an sfixed64 value, without a tag. + + The value to write + + + + Writes an sint32 value, without a tag. + + The value to write + + + + Writes an sint64 value, without a tag. + + The value to write + + + + Writes a length (in bytes) for length-delimited data. + + + This method simply writes a rawint, but exists for clarity in calling code. + + Length value, in bytes. + + + + Encodes and writes a tag. + + The number of the field to write the tag for + The wire format type of the tag to write + + + + Writes an already-encoded tag. + + The encoded tag + + + + Writes the given single-byte tag. + + The encoded tag + + + + Writes the given two-byte tag. + + The first byte of the encoded tag + The second byte of the encoded tag + + + + Writes the given three-byte tag. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + + + + Writes the given four-byte tag. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + The fourth byte of the encoded tag + + + + Writes the given five-byte tag. + + The first byte of the encoded tag + The second byte of the encoded tag + The third byte of the encoded tag + The fourth byte of the encoded tag + The fifth byte of the encoded tag + + + + Primitives for encoding protobuf wire format. + + + + + Writes a double field value, without a tag, to the stream. + + + + + Writes a float field value, without a tag, to the stream. + + + + + Writes a uint64 field value, without a tag, to the stream. + + + + + Writes an int64 field value, without a tag, to the stream. + + + + + Writes an int32 field value, without a tag, to the stream. + + + + + Writes a fixed64 field value, without a tag, to the stream. + + + + + Writes a fixed32 field value, without a tag, to the stream. + + + + + Writes a bool field value, without a tag, to the stream. + + + + + Writes a string field value, without a tag, to the stream. + The data is length-prefixed. + + + + + Given a QWORD which represents a buffer of 4 ASCII chars in machine-endian order, + narrows each WORD to a BYTE, then writes the 4-byte result to the output buffer + also in machine-endian order. + + + + + Write a byte string, without a tag, to the stream. + The data is length-prefixed. + + + + + Writes a uint32 value, without a tag, to the stream. + + + + + Writes an enum value, without a tag, to the stream. + + + + + Writes an sfixed32 value, without a tag, to the stream. + + + + + Writes an sfixed64 value, without a tag, to the stream. + + + + + Writes an sint32 value, without a tag, to the stream. + + + + + Writes an sint64 value, without a tag, to the stream. + + + + + Writes a length (in bytes) for length-delimited data. + + + This method simply writes a rawint, but exists for clarity in calling code. + + + + + Writes a 32 bit value as a varint. The fast route is taken when + there's enough buffer space left to whizz through without checking + for each byte; otherwise, we resort to calling WriteRawByte each time. + + + + + Writes out an array of bytes. + + + + + Writes out part of an array of bytes. + + + + + Writes out part of an array of bytes. + + + + + Encodes and writes a tag. + + + + + Writes an already-encoded tag. + + + + + Writes the given single-byte tag directly to the stream. + + + + + Writes the given two-byte tag directly to the stream. + + + + + Writes the given three-byte tag directly to the stream. + + + + + Writes the given four-byte tag directly to the stream. + + + + + Writes the given five-byte tag directly to the stream. + + + + + Encode a 32-bit value with ZigZag encoding. + + + ZigZag encodes signed integers into values that can be efficiently + encoded with varint. (Otherwise, negative values must be + sign-extended to 64 bits to be varint encoded, thus always taking + 10 bytes on the wire.) + + + + + Encode a 64-bit value with ZigZag encoding. + + + ZigZag encodes signed integers into values that can be efficiently + encoded with varint. (Otherwise, negative values must be + sign-extended to 64 bits to be varint encoded, thus always taking + 10 bytes on the wire.) + + + + + Writing messages / groups. + + + + + Writes a message, without a tag. + The data is length-prefixed. + + + + + Writes a group, without a tag. + + + + + Writes a message, without a tag. + Message will be written without a length prefix. + + + + + Indicates that certain members on a specified are accessed dynamically, + for example through . + + + This allows tools to understand which members are being accessed during the execution + of a program. + + This attribute is valid on members whose type is or . + + When this attribute is applied to a location of type , the assumption is + that the string represents a fully qualified type name. + + When this attribute is applied to a class, interface, or struct, the members specified + can be accessed dynamically on instances returned from calling + on instances of that class, interface, or struct. + + If the attribute is applied to a method it's treated as a special case and it implies + the attribute should be applied to the "this" parameter of the method. As such the attribute + should only be used on instance methods of types assignable to System.Type (or string, but no methods + will use it there). + + + + + Initializes a new instance of the class + with the specified member types. + + The types of members dynamically accessed. + + + + Gets the which specifies the type + of members dynamically accessed. + + + + + Specifies the types of members that are dynamically accessed. + + This enumeration has a attribute that allows a + bitwise combination of its member values. + + + + + Specifies no members. + + + + + Specifies the default, parameterless public constructor. + + + + + Specifies all public constructors. + + + + + Specifies all non-public constructors. + + + + + Specifies all public methods. + + + + + Specifies all non-public methods. + + + + + Specifies all public fields. + + + + + Specifies all non-public fields. + + + + + Specifies all public nested types. + + + + + Specifies all non-public nested types. + + + + + Specifies all public properties. + + + + + Specifies all non-public properties. + + + + + Specifies all public events. + + + + + Specifies all non-public events. + + + + + Specifies all interfaces implemented by the type. + + + + + Specifies all members. + + + + + Indicates that the specified method requires dynamic access to code that is not referenced + statically, for example through . + + + This allows tools to understand which methods are unsafe to call when removing unreferenced + code from an application. + + + + + Initializes a new instance of the class + with the specified message. + + + A message that contains information about the usage of unreferenced code. + + + + + Gets a message that contains information about the usage of unreferenced code. + + + + + Gets or sets an optional URL that contains more information about the method, + why it requires unreferenced code, and what options a consumer has to deal with it. + + + + + Suppresses reporting of a specific rule violation, allowing multiple suppressions on a + single code artifact. + + + is different than + in that it doesn't have a + . So it is always preserved in the compiled assembly. + + + + + Initializes a new instance of the + class, specifying the category of the tool and the identifier for an analysis rule. + + The category for the attribute. + The identifier of the analysis rule the attribute applies to. + + + + Gets the category identifying the classification of the attribute. + + + The property describes the tool or tool analysis category + for which a message suppression attribute applies. + + + + + Gets the identifier of the analysis tool rule to be suppressed. + + + Concatenated together, the and + properties form a unique check identifier. + + + + + Gets or sets the scope of the code that is relevant for the attribute. + + + The Scope property is an optional argument that specifies the metadata scope for which + the attribute is relevant. + + + + + Gets or sets a fully qualified path that represents the target of the attribute. + + + The property is an optional argument identifying the analysis target + of the attribute. An example value is "System.IO.Stream.ctor():System.Void". + Because it is fully qualified, it can be long, particularly for targets such as parameters. + The analysis tool user interface should be capable of automatically formatting the parameter. + + + + + Gets or sets an optional argument expanding on exclusion criteria. + + + The property is an optional argument that specifies additional + exclusion where the literal metadata target is not sufficiently precise. For example, + the cannot be applied within a method, + and it may be desirable to suppress a violation against a statement in the method that will + give a rule violation, but not against all statements in the method. + + + + + Gets or sets the justification for suppressing the code analysis message. + + + + diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml.meta new file mode 100644 index 00000000000..b16412ad8e6 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 05459738c7bc33eec99c6d6b8f458b13 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0.meta new file mode 100644 index 00000000000..aa6506e1e9f --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b4d5a28791112380aa5aea8031f224bf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT new file mode 100644 index 00000000000..fa3121dfaf7 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT.meta new file mode 100644 index 00000000000..6cd0abc3d2e --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 32e12c577ab96df98bd62984641357aa +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/System.Buffers.4.4.0.nupkg b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/System.Buffers.4.4.0.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..c261fa8d8ae569888c40b4255642ef3afd026f58 GIT binary patch literal 78363 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�~r(0B?E_LQt6ou#J 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%0DV%GL-7lfv$jZq+l3F9+zd% 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll.meta new file mode 100644 index 00000000000..fa353346964 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 942183adc788e0da2ba118ba81be0388 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml new file mode 100644 index 00000000000..8b1b5cf90e7 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml @@ -0,0 +1,39 @@ + + + + System.Buffers + + + + Provides a resource pool that enables reusing instances of type . + The type of the objects that are in the resource pool. + + + Initializes a new instance of the class. + + + Creates a new instance of the class. + A new instance of the class. + + + Creates a new instance of the class using the specifed configuration. + The maximum length of an array instance that may be stored in the pool. + The maximum number of array instances that may be stored in each bucket in the pool. The pool groups arrays of similar lengths into buckets for faster access. + A new instance of the class with the specified configuration. + + + Retrieves a buffer that is at least the requested length. + The minimum length of the array. + An array of type that is at least minimumLength in length. + + + Returns an array to the pool that was previously obtained using the method on the same instance. + A buffer to return to the pool that was previously obtained using the method. + Indicates whether the contents of the buffer should be cleared before reuse. If bufferLength is set to true, and if the pool will store the buffer to enable subsequent reuse, the method will clear the array of its contents so that a subsequent caller using the method will not see the content of the previous caller. If bufferLength is set to false or if the pool will release the buffer, the array's contents are left unchanged. + + + Gets a shared instance. + A shared instance. + + + \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml.meta new file mode 100644 index 00000000000..c7be4ebe834 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d0a0082994d341b439ee7e8ecb0b087e +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt.meta new file mode 100644 index 00000000000..7bdf2c0295a --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b810deb288fffe9e7a41ad08ad835c80 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt new file mode 100644 index 00000000000..f35e2edd3f3 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt @@ -0,0 +1 @@ +8321c729934c0f8be754953439b88e6e1c120c24 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt.meta new file mode 100644 index 00000000000..627b93ea4ac --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 011876b4b4422eddcba6bcd873099eca +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3.meta new file mode 100644 index 00000000000..4ddda577cdc --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bbbe1fbd2fc4df71bba55b1c2120d312 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT new file mode 100644 index 00000000000..fa3121dfaf7 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT.meta new file mode 100644 index 00000000000..c4c0e57178d --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9eaa875f814c8e128ab108799ca8e8b0 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..5fa15502c47f9d14590e3db1ce1b8370b4d1ad95 GIT binary patch literal 154054 zcma%i1FR@Pv*xjF+qP}nwsDVb+qQk~v2EM7ZJ)jW+w5-MCYx+0UDN65>dDkpzNz`D zMnM`F1O)&900ICpC_yejFxVIo5CGuwUx)rTtM6!P<3vyQADNOcX*I}zAo?2e6Ew${ ziZkA#bYQYA%5LdvKoo~Fe-=<2d~!=|0YzCdM;Dgi)Rv}czq=iw!(fX2C9xT*9HImP&i(tq;fDngLzvCEkpN*!1tJ&KxWK znNSDYPd2fYRBlGj&mXtF%U7ypWqzxG$-I4EUZB=K9bT8LmAp>qP-}G7g8j((_5vZl87jvjP&E>3?;jgK|9EhLQYUmIAo;&r~8%4xXx;8zJ6m=)w;-75?A|~i22!q9N@q;* zF&d4aC|g-l1}v(K#Y5!Qk)mL#72z|hcZ{f7F(J5G6=BCAAeH~{9K8%GH2acRMce zZ9s{ZS$G6&!Pt**Ui8)pc4_BC-Voq1KNN|>9N7slG%pJqMGrFO`r?6E$C8xH!u;lj zXqAi7SxO4Ak<}R1u~0Sa2K^B9Jk%swhTY^JygXNIowsY%#+8w&P-_q|2ua9zq&&y= zp>_yp6AfL}zy@-l37O?)jK{2VALUK`gPI^?y=5fiETdFgcU4GhgsZl!MyM9v1)7K^ zNs2~BX|*Y2!Z@JO+Xi{Dp(CSiq$11WIKz-n!pxMC3nIHfayTMX5Sv=El`wy2(%F3l z93CFjK6uS|g_sa&5V9towKyF!9V47msznOT)Bu6&sn2g?mrTkr)~3a)0~E(c_^@-( zAc1d)NAsIH%9yGXabsMJ7om1#%76zLdWMMG-nRXkn{_)WAL-5kPnd;mq(0=8<5|=W z{JeeAwrw>`gw=ZCz>EieSQ_5GX3h4Z1<{=wNYwr;*)_%=NG!`WIwmPyDX8=UR63mi zQWslA89axJ)$shG*_;MG5aMcZi**$7uyyI|iWP9%&3c@uaAsq8WOCv8`z5Jn?2luW zWT~7?ObRY31Qku%BQs4aVzHfLCV5P{=I$N+IGll#<>OMIBNB4jdjgqRj|0({v z5zwCi0Is>>u6EwjEZff;if;jP*M#U0^mx?lVtMK98E23!e^bwrH~xS)%fXYN zAF2376e=B#TwR-1rJaMF*Ku*v#SxdDR!@6*VD7B1q%7}CY5i=!>2|Djy-)mij?K_AF|cg`%|o)9@9ALQoHRQ<(ydhl$%gZ;tW zV>xc76Jogc4IVny>lEL7++4Ru-Ocd~DEG74Y;iQXG}-xkS`fMjKfQ2>odOeT><$J) z?8!3xOgG7^(8u(yAwZY`JC9@?a%cPSiY$`-c^L8M7F=BZu|W!l8{gfx@)q#t9@&6% zoH1%<|H=AIlAKW9_$kCl+*6GE2 z^+oN#Lf^NzQ5H7McKEg@k%to+023jH12paJ|72wvVoGb;)G%jN}>KSosCz(aB0wOp6tF;d@lau!qL#Aj_-%VKVn zCNSc9l_5_N!GaO@VHR}PajZft8rrJ@t*MZxf~K|4*q<-uXQVGWjBFsK!jcq|$UP;& zEE=AzfuM1h5qbid6j?8to$EWzSiD!JQPdxF$ei26#m>x1umrV+Dvn+R#mE>QJySqH_vSO3R{no{6=F;!vs!Kkm*=#AIhgyluU5jiM{L;>}+>X`pNLyy__E>!fmdj;W=l2Xla9=;fkl?rNDtvlDu-}?O#55(2k)XlBvX?p8nCM| z6SgHt^bv$(_?N1Fvk(K=&j;EEWxOIL*;5>5J98zESg2lg&hQnwU%i4aRSRKn zCU|HrpOF=`KEueHsjtb`SxuhdmF}1i*DB2Z4CF@ z`uT<~mzCF%yExi5*I-q@g@naH%jY0BmJSQ{^$%{h+lOw{75{Eq%jtX{>FG!5>6-h= z6L+`b>bd>`C)W$O@CE1U41!V^a3I)pDB_7gNI$6Vrrjx&{^qINEar};g58>V0ebvK zX;urjGgpz`W=U3p7xSIXO6U3+{D<7{z%a*4^EQ4%@qWsoYsnyP`^@q3++cMMpEJRy zx!s{|vls7509Q~Jx22GJklw1R2iQlFIT?V@JSq_{9yHaOvz;;3^Jo?wYb zI^$1rwk0OeAtuOzN$!yph`I03T9BQ!)o^^6Z$?1()tp_mzimQj7k!%L*iq;gP~75O zQUQ*qu>GY^c*qxd+m7LjBG@zx;{{$3y77rnnG=7wisuKUPgVYeesJtvnEnM|c1X6b zI)_opBvDAE@$%6oq`7=o zh{(3?u09!dGN`Aa>pU8v8MjsLfhck>;+mu)FS-q1lE&aqxm+JMO|@<$Xz`J&swHMr zHm)$n!w;@!ZV*tCvT6N`Cc-#05Bwcx9coSJONYtM3rv*^3Pww4G?-OGar^a(9m=_O zn%dS^Wf%?h%{B(oCUN7>B?kbYr{Kh4aV8hwEx^1dBgbXv<);5q{TKTuqWQ+JGJM&mfQ&EciV>LU-Je)lMbHW zWd>*EeO0Co>sa?4$Qx6kpwNDf&jE`&diCz$fMTZbuyeG7f)uWU?>px_k;`DRs&0{{2jCh048DbgrU{;`QE9q28sd16 z|JdB!oFduZnND||zYlRAhAj&^P7j21S!4AS>^r%)wvIfR8RO6M!6@y)2)2b%NPWRwGa0G{p&O-^8*~jL>V|IRS`QafUtGD*8qYM5%@~OE z25>EsIfcsqqTR@FAGM2qYC3uabGGH4)Mo{+8?!}U_oTt6Rks{v31!8EdO=z@)(dK8 z0^yp4T;!K=1bb#~n-woEv(vad&C5$_wIl~)kHlr|p1o_*f-ei|MkbjO+*wsfOU zpTE_chQn#6dEtJ;Rj{is6PL*}&uJ1PYrKzR^m8qfO|g)g0x(K!*+5KS9cpl?Q_hW< z?MzYN1ah6TsJ9E?ajciB0ZEJDO8!D@N}z(1$vV6O6_Y~G*+{UZ9ctTh1k7~MVaTs# zaSnNRR{@Vyt`{r`A~QUvV`UE|$ectiQDE+^Z6ZnKXk;B z&)K-a3x4+mkBzWY9f>z87Ix1#YN+-IpMYHo4(6(w33EuA7<1Xa&TwTT6tK&ugF-K2 zwyRc-V&`}Xn{!}oICEk+^GZs(w|q7()_3ExCz2(m)>%m=;lDq=L+l5`o<4=OT*lgQ z_~IBpv}Okbw%QcgtIP15P1+ci1W+4#`>|+;(Zj14b2J z$9Zk`P#@+*7$ecL>#Qa|lYpZXeKrn8X07}IoMpTrGP~5tIP-=u{*7+5$Ff?wG`P=4YBNO^*e|tMEJM@3hD*a_% zxMwv{U;8v->zN)7NSY-)oGm&Cr<4D4f6C}Ey@p?OKu>faP+0abJbS#K6}7ezMP?3` z;Mz};diq!6A(HgJgjb!(SgVc1ZbL34QplC>VW(NWP<-TxU z1*Y7AM?&|arFP>i#Vdaw^s@7W*WML&$BViWgU2S*Do?89N5H=jDX1z5TESXhma3oxN6-$tuzgx6$%3xm#6=apOEynKY!A zMe`j|$3R|XjVI-?7&g;J76R*0Yy(7ElYi`Qe8_AeRmMs{S1nBuuJLx$US#q|y1EP6 zp|a9tIMQ||o=|f#REpSV6IQF ze>ZPFweUJRP#dgkt&+FjTC+|m>^*HxnJY2cU2+0Tco?Ts!9dyp2vx|Rfrm|pWyr@` zhyl`oG`9!c2!p?52XxYHF+pGek-Mns8MVtH?V0wf+SdutajitEM1>t(ftR(C9)3a- zKnZ~Dn9e8mTf9l_XWAtKu5h2%hhIzaXZjh!CK({!%)oTtli=5#7SCxM?A;=QavzKv zl*Q~J4YE0=?qKr#GEHbtLNWL$sxsj6;r8?QwChqK2fWAW;LxE{F3$)tHyX}pMn+cB zBzq|jBiQ;-xsxI$-c!lnH5g@T3 zY_hVQ8v)BRi}#IkXjj}wdk=$OH+hj)9!&6%j9NSF^{Ch$GYNTAJT6l7%&r|FbW@XO zq`9h-R6~)X0!xDKub~snYAsY=nb(@%eSr<=Uq=mxW}wK^Lp`QWlKkn4X|quh^4PG+ znp)4|KZ_;tLg??)b3FUu2c~)wcX#iGQ|zU&N<);j_3_@n>B4&OSoGmDe-FT?SCh9}c{UztAfD=;8AOR>hAx9NZ5KqVu>RYf04 zQuAi-6W;Eqv`n8_*nGB$ebV|JrBRZ-v)zLbK@gB6o(t%q4Av zkU#zgv#^4oRdVzxbKWGk8cnmd+Z?JGUo@<{j!{q+8iu0E>o5=PR%HMC+Q58UJk8uy zQ84XVD=)t}e~k{LVml6qr0UMkhiYoS=2uhjIm%Y7Dr3W*r7T|{eqNHT;?Y$o`F>XM zf&2~uRo$p4gL3>?38c#Kv}(Kur!EJJtiMgOygx@4u%f@~MMc}mFl-GO?lMXO|6yOm zX9M^`y!-tn{^~9KrT+LQdhtG_g)aR7|2rR0n~{`9{f`Hr`q%$MXStd>I$7G=(K)+2 zgZB3$0wBPE^z~wP2O}5YaMu1JT{$Y%*BJ9;jUChNI3p+13gUu!y3^wSuRQ_&D~0iI zoB!Q#{*7FmOqDGR9ZgL{Or0#v?Mxko?d_aR-JSn)k^i?Q>OV~zOCx$aQ)gp)M^nQ; zf0*bP>GkRK|Ch@D%$FEug2sdW$RvX*=T%Yd-UGy0?{s#Hs4ILL_B;o~{w{N6V~iQ#RVYRFuEa^Jk^=k_XTgP+O=Y~}_bkR)waT(k z#qXy^v4mi3;0kN)X})W0BGhfm2xs;VB_mX$W%^-5rF$Q-D)YI~!t#54)v_0!N0rlB zoB9G__^ja&V#8<`V-QTibebsDt)|J7O5h{xJcN3VFc9W2{DDQFBub&j zJ`0TC1H=g#*2Kg`V*c??u!b*Gan;`em)K5zU!-jo5f6aWc%|5%V`^I8?KXc@+Ui-i zS|I*r8wx$CV!&x=UaY<@gyN2Ic*>WtS4!v=_zoM_c!_ln?L*)i1VT#4m_4u_+G(h! zSV|NOoqu%9;D@6I9gUKK&SkL9+&2B#%Osj`zOM=R39;TV$ztJf!AOayv3RA2ZX|=2 zYsG+wnt>=%{^lzI+m7jj5!aoobqGc^GNT^m?C->&3O-DbiHV{`2C?w%xwl-wel@-= zM!NsI@ag?oTAI`;qt&v5U$bZ(T{-BOw!j7}TeU^qly4_&JZ@*5)}W82&_LZOakFhF zijiqz-2oXXM!i+QG&G%NA9pb$wsGRJlC)M#3nkfZ>bcPXAa@o=i^u+ZanY8+EiIgk zYFv~crC5x?#8~=E>dI#uHYX)uBuRrCNH#e1UG@g|Bf}96*|~{7DG#3C2igopZ>SJ0rgblP-CA?BzNuMReaH6@=*~6d|9e8nEtDe(^9wV$*ocQiz(q>fin}h zS`W1wc@uD2I>A%3*|y*jlG*GR9|EzOs{kBg^{MH0(?r3;Hvw4wxi!CzFq{jXu(p7j z<_5<#7o}E}LkQeaM6Puuz9;va-chAT4Kuw7&xR5;x;orQ*IbF(9KJ`!CVpgZVG1|C z5LU#)O3%cD_gPX>v$2CVl1;)*4Y9%V(@a-v-`JeE+{Ib0^W&x-x%J9L12Epe=B6+Y zg8ePzl#WyBA;u&u&M9>8W8l*un9s^b!s(H}rvSNp><4kb`{CJ1k{UC~ z-WcaBGGN>GTh|H?rX}*uIT1|wtsNF+DCd?fBuWkbG4PY+(Z&p!_n);w`)5)a+SCJ8GHkoE-CZMj?_dl@3 zoBnM}(dlXZNiInTQXHK-)f5Qv+f5Xev-utlzK31as@cCu-~Sh{ABG!x26qbpz`z9b z|A!+cHa1J$kl8ru4h%bsZm&~UHnUeRQ!{wHiKOkkyv$zFYFfB0HtVVJ@aw5+FH;vy zaGP4yy4u!tV*~J|62&wBqPct+;u;?{6`qP+@l2Sy{bBf9@pq-*TKnikw0wYu7b7*!eKyr~A;iT%4)70y2%6V{lPV%WAy9;4T$j|19iat} zD02`Xef0zpC0`z(6H)zG^8|r^*MN4cLPXyrBT2oP%3yRtpb|nsx_k40olDP2-l;=~ zl=0&p%t8)RyWzBd!lAs5GOE$hRILde2pqo++zTU+t=C;q@%SM{?dih&QjNxKalwZ} z28_!z`R)X^wrftEN<~vnkU>S>)e6bHE!sl|_Ai$G5|e#FxZ4Fk?Dhs5#f9Hc2{J^X zM=Vh8(M3H_R+k)vyAzG%q4>q~l77^bYF3K$-n>in(LrS}Dq?_S0yGt;+;a=U)F&_O zgvu+c=)yJuy1zC|QBOWlZ7QGWj!lPmHe(R@i#P~$xp_%(SPQ3wKcWMS2q9)1ZIh54 zqw_=qnn4w5Z&eW#o!JHKh9C_#G87!>;R2aztT07AH)@0+PqY|vPB4HooWD85zq7fK z&pE;IHo-!Tuf;HC3l6P&ci}tK!uE$@ra7QFr7Nrw41fUB8s}dM=Raats6#X*3XBpS zv*}kpVp=ePbod9*i7KQ7@Q6i;XiW>4f@Q*4nk7qeM${Kt$am)3EYsN`&b|cofR_L? zNF|$~qwH@-x%kko=Nm+r+6G@#Q>3|!8VD-Zt{r?~5l}APa+I1-n)=cXO*icc0kf7Y zcNjN-kk8~!ijL=qB;cV0=mpLv4ZXYg_lQk0k!11aU#uuCN4#8FC~KL?APF3w(bGE2 zP~s%lW^)@zSqZ)!V6#o#aI#Gcf5xKX*AFLw&w~h(sPcHUA@Ur7N8K7Aj&B3hFAxk) zG-xE6n%Ar5(=5Sj0Do{wcP*%tXz47Kvbxk1N}8t_p(#LsU*Kyo?rr6ks2%8q>#YC1 z&_fZy=png!u*??w~0RM4b^~Kb!Ou%j#LDxjR+;o^*ZEEcxixpD_I;{)8 z+|&Fuo2ilmSvYevv>dJ)XZ_+1)wj+iuc7|V=)V9vH&L^`k%7C@=FSwRcN%G9%SF4E zd=z~Pz2RX*)<^}%fk|kglbF>rbSanlWm_MTW3VSDE5#kiD zCM$LNUi$*pS)P*Qxeh~M5XEkikV?}P=#rzR#jzQeO3WYXpFV?r%lIkhgk&@4fkTa2gvF<6_xUxOlp3KiRl=vYAQ|l3nDU5WX9K5{Rud7A+RnBO+vg*4$Uvs0=>^} zfHD7M11rTvw;{UyzO&|`(228MYU15MGZXIx*~U970sVmpRSJ3!qE^!hNrYs9{FUMM z3DNcnen$??CxX~RukdSC0)nm+VJ>A-<^Z`tenhnRClq-HYZ(;2#EgZz$m_JkSOJh4 z*@PkWB>gj+kwF;ddfWmnJbRw@PXzL=32Do$lnfvOhr$m4wco;I*f<6sD#Vo}*6}Up zAlI2{gUNC?21!LyJ<~Z;WR7BYL6cF1f+%JR1OQ_=gORqIK~444*vr{2k($9e(7G|& zbkc;4w1rVTJ1tjQyLzB)mKG!ZjHDB@XlUp3YrWk59V4XQ*5sUnVsZ$f2C}dv2K%yU z7p{LV)AE&|a_Zl)l`_>cvnxeO9wn4|TZ#dF!IB~1U;mpqnKevd=f6XNfuy9oi(@NE zseq)c3x%fnhs9!F#KcQmkzme(a~9LlMjBGQ721)|IVD`?STAoar9+E8`O?zkEBdE8 z-W_>i`igFB*Zkfz#+9QqNl-vij9XFlv79xT;~Uka*w3C~pu={AMRiRBfEKODMX6SC z<1f|bcMHE)Ju=yth83fc;8dLP5oL$+`pV99vCOIX;J~&%Zdplqn z0Clyo0L~;JUzk9T08?T9c|rzo{_O~Nz92#+`EDSMve)84w6;ba07c%SWCennWG2-6 zlxhbOEoxEBCFc;Ka1zc+taJKg6I<&kRDY$qM|4 zQWa_wD3a-C4w2Riyl~teBJ6HShTwdeI&zV~LH2K1> zMsYD#Gsvpax@w0K)+txj=eA&H=|;j9Qp>R%_gXEX&32yX40(JB5LPo!AI+NP&w|Sl z_EP$1>BElKq23^3-lHc2UaL!_Qp@b?n$4UA^@XnAJ^WWwCqd!6bVx*kk@bbuS;{ef-w07w7a6}-^N1V$c(hfH4h=Hi9btfjBP$Nr3mr?qp zbJ;^$Z7`!2m5p9_O}4d4Ima}8OvBf~>;OB#9!PfwsaAE)55saU2c3d&&u=_15}HNs z7U;0qfIPh^CEW;%a*5EPlra%Y-z?_zd2vNRX82}##7K!Bd5}-+Z2u6CrU%N^ z14t4rpLV;ow~Z60adt$5Pt_eEm*KrJck0d4qan5>q~Idt05bW0=Ca-}{n&Rtgv@AU zvA&V5DMrvtzS2EV3Zam{7aBSC7jwI6N-@r~ojA<&Z(}>Uv@s3_zZ)22)AH#@9p53T{9r|w8(p2DGj8&2es7XYLd%^MJK@yP;Vxez$&RKL zo%9t$z~m!DZ#IWGO*$|yQ+&-6f242@@?fz$Ml`-WQpBNK0ELGx&DPV0QlbsFuBCl+ zKGbW8CR(#Uf>yxhpflZ5eC}k#oi8`Lru8IjUS(V5dLF+&9ZRC!jcK1GSuSPEBlEZj z=9Jy!4Aw$onc^2;;-=)`e)7qrO{Tn875005o=bo`O5)Wy^)vkQ zJ^gCjWbUICw5C@;IuY-s6Yp+xR4xAxdZr>4who1QH>rB!@xUk>|0=>em{gj#27K(G zf;f1`xDw3dfTL6!43>l&`+^kfnRxuylitXs8-?4hz3R7(t@jp(MB2HvjN4P0{!N^3%Ap5mrN z$djwvYDAKPxo=#$vmQ?+sYK@{UBG=E?n6c3B zd2&WYXTyKDvws&ZBTvtD)YneUg%5@3#Cd2LIbp~~OPj`yG>R&Ww^GWrwsEb9Bg7KV z5G4s#4Oq}8^IhVPZ_Ej#FIp2xmu1l;)4?(?%v)ZGB&e|Cae+y7 zDj-?$TK!M_M>V>CfuP;x+HXK!dI51qKQ_h`2X;^90vN`fN}{)`;PVNg18{4W2!QMulrz{psTJP z`}9y))X#h?55oz%fpyEprIX4(0JK3cZnl_LCJW7-w>-TBpB;0}Z7#E&?kLQ7hh=|m zoOH1zJCS4~b78?S4D*xJF*`JT+HDbYQy;DXUp!0gq)on8!nvd8BOUi!<WP{rN$+FTJ3NqANaOWaaq$tvuSj5zvEl{(RmZ)u1uv8;f|cIWkpP)lbJPRo@{{(n@nAoD+AO{QsP{XyX}HH6 z=$%eBvE?t;?)a~MY(IIf*hPt&UAt23}mx)kUI~u zXczv2U9!(<3@(S0#i5r%{!^4F*TCdck!Ul{lQ&5gtp(%_vtr0=SxhXV0Nl$7mP^TQ z#0LeJlu!Wu+mmqZu#+p_QrcAVM#7be?sL8KPrT293Lg)@wnef%Cw1O*)H7JWzIYzY zUE#6TPK%C`LNt4@yDf}GQ?l{9(Xl__95zVL4jfqMDMroVE?V%W3~K>D?y6MB$qyjG z(g79f`w=!_VY~4fd0bI|%2ph3&Zi>su=tuC-!*j9zuE{Ci>x16pxshGW+tx925q^s z>(>5=z$pp}nqL_&hUl9giL)+;Z!|Tr7WwY%Tjk9kK2{}*D`j>g+0Ug@m-RBS1fkC* zKbkwA3)FodD^4hT$2!@|6Df^1Ws%``%9RwnjW|8Y$6|goqR)B1lgl3H8E)_FyIj`A@jnve zhPuwXjc}UkWxUoT%MIqT?^s?d_GnyJn&26E4{|b?BQNDgWaf@pXZZYO+ zU8IaVR~RafwU-@QRJY6K)m(&@gt6C~^#39K8TxD0IM?|2!!38NB9;4aqeD+ZBySZ@xf3` zc~Re_2x4Tfd3A8q^TTdnJsMND<7*50+6Z;w0z==5R=+aIcLjPF-F5p3%B5${RJ%KE`fvWyy{Pm4l1?Bbv5o@amIvuy(}ifshGL}0g8N<*`cPfD8WvS@DixDi2G16 z6)lWHNI>Jm9A!ds)Ujj)jJwvJIEhDCy4M75;_a0n)Mum1d;6Cv36Ci15AkBrlp3ORLH?|Ak$Kdy0Hnq`@r3JA$2nvJ+hDBr-!%))}4%49nwHe*U(lHy+cmRb6VcaW{%5!|RwvK;w&Waq{L^>82N6 z`a>Vu0**$cGgm$-mKFpgWgoR&n&pv-yJrxK6%B=Q7ut>RIgCPU(lQZ3OQ(yP@ljhYW&h5!1&vtF+FzUTywC&$i>oHm-?ipxL z>;=FqO)8LQsa7oNGN-rfSXPb$f0$h?k$ITwp*807cgZB@C=GFjjPwwq7^7VXtkDMJ zusWtiU157s_^^t;TErVnQIA(Dh8api7e$Z#-oBu(w8Q8+8&m-M10sx!l~K%VBbpJ= zOxVCN!N&T9>Yfeb>$%Io8ln==XyPRE6BK)gg~w2gUkMHoo7SCF#? z{{pauD8}?kCP2Gcp8zw#E)0eZ7z`_LC^3L(aj3Lp<>TddR_wqVN>J}Qf5)#T0(|f! zg`OWXX}&NHxvzlFNx%tTBi2)f3O*8Vq3+2jw_8S>V%mH9uBmUfO9no?O9r^6OMRvh zrqFkgkTqk9oXR%vcsN`4tHxjfRFzcX~|ZUDgn--?ngH>NGi8FksHr!&5S?5f0c@#dOFx_OvH z)SY=$kt$ndd#@gom!&G2-k>7gC6?Kv?hRI#-zaqlZ0u*0K-j< zU_$}($r=P3X2=ho&L$M!Cil3K@K?V9mIo{9sJG{(-Lt0xAZ1W?LEV)-La%~#Tz7p~ zG}bG~vn4|hzifoGu9xrK?OQZvKs<_%9B)$82slB54+%SZD3qvv|BuYwt52Fqkui~$ zxxPUTXo9!*8WX8BCDvKrr9p1qIlY*z$c+s#me)v@^?8eiwXL1K@?{CzieXEAAwFcy z%1hgvRf_$;KT8H{7DR1CCc#0&Rermt!5TW(gW15mD+hPpdtxls{qaVnzu-5Av^<3h#2ulUZR$3p1G7jpnVB>uLSKa=!Dij|d9gg(rf9xnc)nSabFC%);>-B+ z7QnR@Zcolz6+L@MzsYiY;ugTQ7s@<7RFnCZ5_>Yr{+2!Mr#>;}#;%f{O(l`Q>`M81 zzie>^X^)%wLA)3rZJwW@0u|jO71YF1krUKEbg^wzOc_tuV0Wv)8BXxk#s{|!jJ53R zU~XY^~UMTet7${)D@Vj8>m_F=I)(z^4< zGIseLx$ly71)z2Pb?lmT=#od$>jAw5#<`v4+}VV%uLHe>=h&&@+?j;1F9*E^jCF$_ z?aa9g)xNVkasTApfvt`q(n8YVV4rUdig>_SJ43gOO|Y*zjf0Hd`2-QW%@OkA{RJHL zVjcC$nA4kuXXu)c6sX)<78^|2WO#2+_eNf|UU;P8+?4Bz3>xzgxj7YjF98YqG4h+= zJ24Z1*$BsILS(ccHkuO~%8v;b#6}FVdr6Tp*FS&tzUGOdVETK9kIS>j-gfFy7-a6n zE&n?Rm&W>OP)+wZ=Dla(Hnd0s?c^)(DJ3uVP3ne(n`<&(+wPF)q)oaj zqI1T_$SaL`_Vm%7ExkZAN1{>IUFr=OIsUw6@*V`r4RZEe+|OPpgTimUAk80YWE zeQiv$o2+PTYxdzWBz-jDpJ;uj(`RPK@avr8Q=%EBvyIKpC7LYIxV=L?%K? zJsG3ngGZCp1gX){=PqaK*zxMv`8OJ+L(#|7$1a{twO1Iez<^8e zpDtzCQ+Fk$3md(^!rB^9zG4+w3aOKIG`&`IQT)gdt8#X)tE)E;rG2(~u}pT5B=%qo z_fZ{rF|fjz6%_FTRlnK&4~Jo#a${txdf5A|%^CPWm87}EfL4YPIObWOF#@zde>keg zn&lgq)f*LlD66%#My1alR-Kp`CTYjtJ^z;5CsEDLJF&X!l%Fzy3Ke|-z|$^1Vn~g> z&y#oKaZWm|#S;^58uN$5f(Z5dHRo>fUbZGAA@&Th7Jzvt*zqDVbWj=a4Ht9bzaI^H zJNd&gq&%`>(Em)Wd@0aDz%B(c8(apu0BJ!DHU}2OUTO+^^Fr@lS!>Q>8C8M#T(2~m z?5iczpgQU^xbUqN@c=E98O@R8Eowv#?!NbeWk2hKqsScRR?*Icamdv|&)_>`2hefQ zA9B3Yakx2V_tSBFa?U8AXWQbKw?WIH{!wA;VLwiYG0*>-_?R_^nULVDh6R_4ro8bO zBATL>t1n`F%&Vhbdg_{7nth)`jY+k3%Ki~WbxXe_5mzkcNy557T#FQ&zoM6j-@uK4Zun&CO|)0pD+^BXND>ll}$0)!gE0B!LlPI$D4V;za|5sxpXdBj>QPlEGuv@QtUJij`u26atB; z0Q7=U<<`2?>46%TsU_oesn+?Im`%asp(yrbnilqCnD%*>tWNcJS6j*qZjG}Y3c9sY zTFU~abqO;K-O9vFGaE)%d0WIxE4r;azIDlCS&g&aov^ zZ3*9sln+Nsy6U&OHSjliLC6d{x@{xAWy#}<8rNSmwED`2ZQ1FEREiMC7_Ar5ZLOA7 z5u>^Yk!&r`IG+1?(JarpSM2Rm?SM~jK)(nu>+2V&UeqhpmE3WT_-jnfeu(&6%n)(E z>zC*svXL1aImv>6JRG)pH0|K00=RSfz4IX41^Bxs@35yB9-n++&)Bk4uHxUsnEWG~ zuqSd4&(EdaA;Yb)5&e3>ZEWG7j#!{>jWa5R_foorWcphQDa-cO$WSv}#tDw9H#t8= zI-qx=JNm$AQ3V^sWc^?$s)>Ib3US+CSOalo4u6IGSW?CFli;1j3zT03-u#7W;GONv za|qLm6JPdbGb+VWyB>YpX^~ABsn*!j$(q{RqU4G!KTlcfQg8}o_S3db)!~(jYn)DBqI)RYH_TCDBEBI2L{3HhMiO zYW=@kGV#l0-C%mbvc&Szw7Ej%GJi(lH-Bc(hetlYu(#*+?H|;~?i|G@x;I6w_`aCv zpq_Ugq~=v>HO+Go4$g%xa?=FVdY!eP+$SZd*z}z1kVo+3i{3G1wB4SB^kMin(zV?N z6vBu4x6nwNUG8kq@QJR<_HyXVYV+I1;04&vphbdpFLji;JaiRmwiruFJWUV01UiVd z-O(*WnikqgfBNG#QR1m~kK}nL4w=nf4n9tn>?yGveSBy+!oJuj@{?WY zkmnl0nF8CvOZJ}^cJ2v+EW#T(Xcn6X;-1c^r(Qbu19h4i)(jhAedBRbdz_kf2g<2) z*FobU9F_#%E5#yClEpkY-ABRby)$&)QV>sGRWLMQF6T~L?2t(}H+lYU70U$}>s9j? z4L*rF^+sg&AUSGCk(74sBHcj)rt+y9(+|~rYs{y0iLR(5Szrz_O(^k8q%#s0_hAf2 zt!K35NXpO(4>ljjtbVPx#eyo)G@g)u^p`$u$v_OovFyVHJAiE*9u0E5ziyl@N}X78in1jkM-F*#5(Dov792M2~N_Xc3MA$(2$#Nea;$SYv0qeNzaGj>06 zM~N5_7^S9|A7Fod!>5NGe)piYmRhM9t!AYYZRUD+h-pWQj`!x1%pkGw6Z(B@zG2`* zLDGY0q0fJ&`$6Zw_ac8)8Bl!S2I%YW|L}4FHIr0y1Ic?)MSj4)JvRAcH-g&!;8*m| z`k_B+e|){xY5orYTR^10lw*QglC#ODY;Ar76TbD7sg+c1ei$O(v5N-!f>0FSOVMtZ{;Bn^(KYjd?k!1QZ;PW&r= zM*j2<$S*tKmob-n75tp-UyEJA*&%!|cdSZ0_CusU0a`788DUcqSScWLHIbQOWTqly z)^*6TowBTBS=NQJjD)bWKK3>6W6$pLdq>|aSE^Dzgl_xj*CP6~-wkmc+!14E0+IQArn_WjTA?cta4TEy6pn+CUz7;gs3L0t!4L5@{lb3g8T%rQ5-*N8TInKa` zm9{^d;seWEl)Sq%@{p0ic(x=|MI*KNL2m4ov`8HiGxD<{zG)~@kHne)gRByzr%&x? z-;i6V;ww@U;t7m1-!j4?#jp5%T|WcNN$fGRu$sNbg|TA{cx;9d8euPU6!Qx|Vx$&+ zjL*&Di5r72VA*G-;%SjX=v8?MKZ>PL>VZ=TE>>8w(|h<#@n8d2IJaMNdJl4>+0(bs z*XpcQ?lyem`kzp-_am%m+Ta`6og^^MvHDDRGk%C}{{KbWd`epNlpvK7U`%w+Pf3)D zYB5G1GZclMUO|F!QS1#;X_3xO>%#Nm4e^Fz}tZ6#U8QvIKvqr6#tzd z@hvN}(pw0>C}ufO;x7aJfaMsb90QRYD|51+D;MNinU(zuBK$iZ@Q+bhMpW`GR8|fs zKBa*OrIk5_Q_G(|imIA8{xYD@=UzsJaQy4x$VxF3xi1{~NI3G%a72 z{Z{}zfYEHRLOI=^2lWE2Ot_5hb;1uaxxYY;nmt-o@6aGaTAKeQn%WjAEzvD;@W5N* zG}Z!Y`og~qX+XrIosxvtuCW(Wapoeb@PP{+7n~ zrBvgtFnSG_hDJ~+{|Ny93O*5EpZ46HLgRf{|3jT!h|F>-bK?fTz!9oDM2ZG;+2YT; z%kdil-|F+_n8tY-4F%m@D9uk7;r|=rPouG>to%E4;PUX>qLx_hr#pezl{)weGz`TC z)nYovMAzu<$>1&QQK9uM>`7gwm#%|rdHDBa7S0Ndcdzl2t^L?`+RE);wTt3^3twA5 zhq3FKCWIIasTN|f;LemqY26*61vB-4mPE8$gmtMlbopEIy1N4}()FIOt~KP9r-og8htyxSvW0Wt^XO&i-L>AB*CSEl z8W_uG8tTEpeFD7b=}Xuk7EOY=VA2U-ZA%dvze!Hy){!9j(QwSEJXJ@gI zM*BG~u=~QK(j`jiB1x(ANb?0qR_J%EB+W15rCAP7dF`MQ0rbdg4N0jcdt`Z3#}U9m zP$FGNi9^r`Yxge$5b=LpDr-)Hy~r%t?t7vcB-yhA6W0k{*ekla-mXeGN0lcRqqlomr zf0GOd0}Q;vq(zpt@7X^`dI;}_dK=zqmsZmn%7@coT0&GsT&iY{lsdyF zb2;0OpS5Q8!oo$o?+ssyxeoPU&rT?^Jv*vO_?9})TBOwoMsanH zzT;|XmeK%P@?6cmph4Nvq?)Ds_b2$ZXr@iS7D1V_(wJu%O;x0+5~T1N%0PD%hcc6L zL<4n7mYGSU6F!*f3|~pz$?i};kNfK1K~dFaMWI#um1oIneNNu^0nikOO#K;zwW!um zOPbM8kWN}_(imt#!~0^xnv1Z~2cROWDV9sh;m6zQH9LymZoLVzER0d#_e#0ztt6E5p?!^8Nk+tl zan>tKtQ*C(C9^n(rB(3mYE?{eKPnAV@%-@^euMaW+Simpgen$XDQS}S0D4=M&4*Wm zt>1vUBfXmnbH!@ekl8(*IMZ2;E-Pf$3CZ`pA-mVgM^$FEilyk4jg~^jgEkDt2t9|Y zSgK8SLj1uyGYizxn&D1D=mF$6^)`XN72HU}4*|Ptf^=L+SM>@bsb#AnFbW2WTX|16jX$Ot}$g4 zjS^DBN&*CmU^a9DbWkT7B6lg% zBhD-;Au}JT8vP7EG)xZ@EYea3+KFO%-UbP}EsGe?(+^1+gTHQuUi+Ns&VoMdfHfPbPn` zyHT!?`;UiAzg<_rh9h7#)n3pTbN*YXT*Z(Z*T88jOihs<5gl&C*@s;^A0J~g+0(E) zF5pN=z(A-(NGPa>>Y&^Ma>;r%At{r(q^^|}ZOv{*Jj7Q5=>W3NRNoU zHVp%uNa@xDA_r@tSU=I)k?T-DJ<51Ol6!*sRDC;O^##N99;`ps0~KGC3pFaoIW!Y$ zR}ifo!8`vk!Y>yV*j>W@8WU4FtJM%8w(fm^8LZ4xN19R>*2RK33V!o=?{8HHl~sOQ zFan>+lr~!f%O{1-*60@ZS!Ua~H@C0Z&y;lLoJ%Rb4%c^G4}JSUVg_}c91?9>3CX~c zd*qO~(^ovIlEJtQ zRN`zw5lUni+scm-`HK2Hdx6KSldMaXI^b z^8q$5$Jbr=Q&~fIUU{c31auq6CKq8x=i%*mo2Z+^uU|ssVr-EAq&|$UGHxe0Vn*@o zw8Ai<-COEgF&#hY4N%JRk78Oo+rJU#QJUsnf}<<#)aDqQ8~e`-`SVhIE*GU!mvX>m zKHxGAxZDR^&H*oC`$Z>SjL$9XS-_K|)WZ~aFpRRvQf#`P_q`0GV#>~;aRomwrb^No z=wb6Tg*|f$vxxF3qB$WF^1^3>JNrZddK~;7mH(}TGJSMt6{m zn=x3UdqruDIU&5^7rT9=zJ;)6Yp~atyClTy!Mc)+X zk>`+35U-SG&-o{Dx37=#iuTh)(bqjV4))Du(Z9i*F6&*`#x0%&=u<*hP$=+GxO#PE zELgqbzGqStgd^0>algQnX!$pl;|26pFXAg~(W%fPF|?GMy1{1YKmIwMp%?|D`nNM92n?UVEAyqwX=)yEDth&a86 z&g{^Fd(bRn1mbwpB@kT(xhD2NmTY}&v?&X})snQT^Qx?lfr6*Oy+HTq!^kQ2$otEE zep&H?C^aI4BLd8JNcNfgV78Bb?)5$v0f65&rKI|HuDd@(yU{eLRsv{vH$S+WJbo#NITfh%iLZbU$<;5uU%-Rw zrQhvD;Ep_DJ z0pC^+m=YM^A#TACP8@PJ?dNtZsY8tz7;_NL$eIpB3_NXP$xiOz0iWNMLA!|ZTRNKt zWgIVG$j8h6U8o`uLt18oRz5_EG8gdpq@VkX1$=M(VRV2ipZq)y2rj|%9q1OFiyz)b z;Lio%hv<0G>8o(){wRiV+=k!%n5FiGgCbLfVJr=V%A#bd{LJQv5PZ8nh2O4UkKOy& z4*#R|XiO77%t?oF>t4N9DlFW3;}-XYfZ*jZOEE|rq_mqT zEfvc%gE_K89`rvhDdU&8RBm@D*F2u7MNeg>Byvx2czy=A1>(+D90Od9YbKg=&16Dz zwpO45uc?&0Yc*#_Mbn&HE0%W|AZ?G)mnqN1=re_WR1jJ8ni!pGxtc-G#u`u+;{S#5 zh+KPG^ra$yP(!5(p-RD9uOfdadnN8wM4z+h^AxE>KCd7a=7jA4_sed>c9$_F!f~&~ ziJy!nn-WETw=c)0pDKc^)UplGbC=E=ub0lX^o**He;3Nn!DiO8CW$3vr{sy#WDzP8kPr zH3%PZ>oGb6A~_zyW{5`4C!Y<-$K2hN)bA(tF;~3QUcrMNp@3RN?`FkX&@jN<2L7P#W2_C z)fgV~4M=u|r?bWG`hCa$FZzAg|Hb;fIi%lXA^qOb(61ukoiE3!FJQfr0bRo55a^Y7 ze+7NR<@L*yQ3PRZ}6BG%Vm_bY{@5b zv`b8@25K5QC76^+*kz?vpN!g#%uq&4tCp7K1fc)4G_HsaIyVf$GvMdPZ;a%qKn~4&PKc^*>E&TB)kN3Ab>EDp zO#IL*M9Ax$JgNxSZ_#PhmsbzF;TSLgW6)!tpbLk+Pj!|8i_&(NmM6@`GX6acvkflt#x1oFRPQslX zbdQ^NYC_e|%1NWtr;|zAWBp(~>X8~mJkzg|KChfzA%l)C}~jIL9U z(5u1iX!Ey6tvJwblHM}0eJcpyvaZaS<-f!ARH$Gg~^$>rE$~97AxW$w!J*|{9D9XwitmBD}bB}L)M71{c}N#HC)O(A@(=0_<4#a{du^| z+p!1;8Jg6~{@ANFc^=HmCsQi4ff<~kk59dh#$VejyCJo5&(w=4dNa=74_DSg2-?c? zRA;WTL3Qq~Z1HA+*k93tL#SY+}VuOpayP z5sldiQ#=Z3{gk#$Saakv=f3cU4Pz@H{KYqH!1zQC*iI0I<%D$vLRkv=@bdzA4nzAu ziq(`bBJ#D4{-Ca8e0PhTeX&P3P*L1pQw4DsGr?R;u;f|Zfh$zgA~+YdF;mSFSx4mK z$KX5-XowU2_h&}*Ujm}bLb4u)=RLH3jp~@)easY93eL>ckHuAz96YN5BaY6Tpii6z zL9%*iqMeFCM-J{PR3PMs26=CT-yWac>bS|diXHN9cYfzEL8V=Kw`ze8=vkW}|(!1ZFZwvUo% zqk$;ev|QGXe_s}E^OWP7BHWgM3A^NP%pG-7`}wd~%pdL*Xm5@aS^F*D9y)~V3e~EJnD|IXZV|w6J)%DWIFb?l==S0C!N-rgb z^|a{z3Q*}5+LETBJFdm;S(w1hW>mwTT>}%7jk9T$2oh9-|GEXCH9au9hcum~X*SJp zEsavNV@@t@(k5EQ$iXbugeDIz_~t6iPqXz*9JeoF{$&~E9u#Rn%hlppn2+^Z1~b}( zh7+-xuL>x;j5lF%3)c8l6Kc!OBpWz5UrXZjtg&#Bu*a(wnsw4jG)x#{fE7i@I+30A zo(NWDnUp0S$r5kL;;e_M_%Vd#!kD?Xh-!O8ya4!uChW=%o%qWU{xYQdzS%#6JN)oo z+H(JLu;q>m**^5^0Th>CodgGeH2}Xe41OX2zl$9ab;jzB!Oq~$v2B00zyHMm@zZQi zUlhjqUBpT$t$>{;73bE94zB%H{yH}voyl*~@ESzHW|L=V3CTv}j_UO(AFvX7? zuWn2UIUd=CDSqV6>hhE@z$2GqiXS;r)#d!Ol!Yk)XFj+IxAz+SwuG7ARK2ai?~*X{ z8&NEu-&JAex1v}+znx*`3n*4TELJ`w*5I^c@1X5Rcn0@IU~@i+N9SO$l2O)u7**+P z-GIksranlKYbrGb6l0=hFPOr!x}u$idRUE{rFgV^6V#1el+tV~@d1p&Skoz_V{MRP z5u~(;ubNg7DZ!Dbff?BfG~nup1fJrkkM9j(bbAm@Vl+%mO3Sia!9E=f;8^2*ZQRE^ z#mi_ar71L&jo#&0v}IT{4U3lWR*N_yT1|rkrw{}s8A?|5hYV#3(89CNX^y>Ltq2$4 zVNZ6Rk4}Z=M-!;+v;7xQ;ql!{1)N%iiW^Qz2~LLBRH4$G(#KNbn&VY0%_+Aa^z*D^ z^^68lyAjm^-xS*lLhXRaRRcWAbJ_WKh@OqsFi^l&I5XkbmdtdImyx~kE=_%O{HM@w#ptvH!!a1bFMCE$Hk_`ciycs$$b zS!4Euus4LGkXnVIYZx+H=X2LTev-BIp`PT!r#b(@Pd$E92`w?|LNbO6!D2> z#3#lZzK;2lfyG@(Gx-i~#B4ama-~(I!H5GHYVSWv!lK) zYuQ9U+m61C^l`%}G&ZTUqu$xzH0Hx?=8gqkHm&6N*e@=;41C-RLq2YJGy!O>gFfj-9PnoS6AFQI z!_g|YC0rVCatC1`h9}&O5%@6=;P!T*bjOW5Cxjt;Ez;dN1e2d-XHu>ANiqvsv^6kiZZ;<>?2RpPoBo6zM;2Mm4zL5HtM)@ z=(2%Nu7yt)O(Dm6g-p=6n<@82eRRlW=gGsW=wX{E4ksUXl)LzM^4BW*>n6&B zNO_3duHOTM-9OmuNW%+5%xU;Oh!wzZgRPE`tvYC{g#(#o*0RF%)mxi%YUo9H5#Izp+W_y;HOz{DVbD*nLa`6S zj#e*i$S_x3(~#k4^@4^BcT|TOgYJ8(sUBJ80y#!QqJfFYhBVu;K#ir%!G<*3u|NvX zKLFWrrpjWdZn9T@%~^3a7aJP{b>9WoV z=Ts=>Iu`^n2yEcXcMJTyR6Fcv2Z}S|ZWQn?L@=Ej(C%ezq|$^l zl4m%0eD!*UlW)dx5*$hDhSbZED6`bcXoJ(&EpB*9q5r--Y;*SDjXe?}As1A_9i zO;CBZ38L4lwIc{N&{8q^fT+@(*rTY^J+g)tatpme4Mt$8WF#sXiAqMIl98xrBx=M+ z1hzMHENG|OCkLT*Vq=}eRyyWghimQ^U}G)g!u#P#Xt=csbgqXh8E>`X+>9-GuF|VG zcUStn^RRth;y2XGsiE3CM9IAa+N$jC;w|^ipigMPHdG84E-qOr_vYGb^WO@Hw_FEOui<|i8a zD)@Ql(T2awZn6Q8HEo!QXw1?QI&?%%Kl@-7N4w-_)KU2uUO{)f>R<%pD-jGksk<(4 zU-uyZ>&{r!iy;451R2sRPjmd2GyHlojKBJ12$}FovzYFf#*AJgY#(z+3+Ba$iCY{D z)0lJao9$O;vbEgq+1gk>$e9arvV6L~>n3Z{lA+Gr9K5sjXtNIQS&|NS#un4zc&x1s z^Rae1OvF0r@aOGxc*%F7I%lY#17LeiUh=MX_`lx~fAxJWnm^V7b5{%IrOkCzICq~Q zJcDZ58C26PJA*SFuNIr?2|pdZcs*?w7ptd|*tVYf#dh_iiJj`{pJVOn>6@`OdjE8+ zV?F&zJN#F5#=ol_{=v@pTifAJbjHuN!xuZ_|FE5%o#||sA8LpHmd^MuZi8RCvx8~w zZNa>fOtbLB6Hg?@)<#Vf&#f-qM5hB2_1}NPntm{3pQ8pL&hD~{wwaBGCkEN9+3(*f zqKqAR8MyvHne|b;IU%EX8&ZP* zo&{#Zmy{qQ?a|JTC-F!aegb25W>>ao$#@NcrQ&V~f1`p^oA~I|cX39DFUSx@Ekseb zbfTzpidqXrJ@h`3o~=)O0)8^a)B{wfmJy<5S|-slIW40>OS8|4c(7<>b}VJZOS)wa z&z==QiTH*}!jhLg!Tu7H=}_cs%u4JpH8jK}GEpM_QVB2PrrW_3eDyWhk`GEW_Z2@8 zmg0jRU$nn{Yf~3msqEx!;lZ|DXxKeFrONj($3@)64~6X7xsRK4ZTyqoW;;q`A|L{8 zZe=9NiTb$j>79E~)JwWqFF#+BUY=M~FYjp4OP%ZG6>Yo4=QrV(z&%5zOSt?ug;YbG zQlOoWJZsu%?z~VxL(Tg6uO;c{n~Un_11}LjgvQaagF1D z@vNyT;zUtT7l58#7S@x#q_Nm{7uD0JTJ$u>_4IbGr`f2YUf*6(*K_$#8Vxsdvw^Ne zp9OWzg1(lWV}JJr8e8)=?^1hq$to+fS6Rb%F`Y55#O5GJI?qA2h2|g^HqSvy&2x}J zoO)dC&q1#91O9yPWN6;=?DE|1v)bVY{CVD~|2Cf2_^fvN0e^mX`oE3mwLYt9Kj2U6 z?h_i{Qo@hrj)&X9=K)}wLB}7r6B;vL{0_W^qg4NXB(h%mFm!;d;V6~kznJ0I6Jh+- zcZ86cwH?HC$JA%E8e#jGSF~VGAtoNPVwmi5(8+v|BNyao?nBgRNk6m0U(ekVYbvuF z>rm!YtX-L7u})?FVY@P4^0lar80yE_=%!7{n{~?YAL@wzEbH{#5_Gzg>-1|oeVtw| zHtSUEq*Jl2PQ{KojkVQjtes9{opss{|Dn$Kx3|OJ(;5GgcKD^v_*Ogo-*mQ#e{5$H zPjtqAPdofKcE*384Ss39gBjh>f_XWaQQ^@?A03z+XV0plIg?{68n(5FO-*x~^52ya z1-#_)q4x8f@WH1!6K57{8i{IfS8HZ;LpI^LjU`sVPT~w^jV|lcl7@qP>{5+doW0@1 zCm&y#!ZwIk4v*56!$D?t=P)v}*mz;D)rQ3?tP*yxq!m_G7>#|4L z-@s(L5w4~zZ7^IM#z6xPI2(f5lrQC*8gmDY%^O7FADaF7V@>{C!x2lQDZQ!5g;y%u zxxKuwtqZ?5j0`gZ%(0H!!MH@x}b#&za$CdTmvs%`O zgT=D`w7INbTePh2ZYk?NUe?#P?WSJbgbxEz%(R6I_FUe)cZZwz_J$6;_dZKyk2nG> zJG#Y(!)1SJ(XxNMrR=j>XvGId;nBjsrhVaeaLMl08*TMaBg~YrL&p}Xv0-__`xAS1 z$%-hnS43z8j+)q&rT1U@z#l#m_J={cIF0YfBm$>s>gp@w8nwS_fTJaOzTDVm^lasZ zXA9$-iJwnrS>W^ zn2M&GH8e8u)e+Fp#`YRwJuBtHl?300raLL{k**Wn4^n=LY?)TuOg?n zs~vG2?P5ioYiCC<>uyI}Ng)bcOHS{^mz`eF)8?*v!i@eBLMk-g@ToOv>wO_@HP!?E z2*&NN0Dbky_70xTUxJqC#0_0^9xOA!*vqRV45wUOA!X_GO?W+`%HN(2ur*L$CY*V! z+7rp}y&z<#1$MH>-XYni@T8QC-yGKPGaC^Kb;p>D5_wv)~okY4T zugKP?trTcKWu>&y9*`qAgjo5GW~J&*Rj;$V+f6*oX{D^*K+H6Zb@9Dsl2*5RYl(ne z+EUAgWt4*#TeHOo#Bly$Kc1kXlpZ;|1BF$x`+0IxHQD&WLAYLZtk*&|V|J}m3|$PN zbUdA)brGMsm4FehS*l2M&TY0J;H@53e6BW{lqf<<_a=NLS@HU`x5CG!l|#U;^Eb~M zShZ;?5810G$Y8Ipq&pw%xR(p}zJ&^O=0>$A+&@>J3PK5f!6z$w0^f8S%0~M6C<>CM za^g4NsGN~x)sh=IE8uSM4k-WKg!Ps7q?Biml=|$E(w;e~N(WLpklNdxly0!&<(4kF z`&vqpi{Ye!aT9as}ig1>(io>~^p_Fsl~JPBe}c0cGJ)4Y%!7Cq4u z6XdvhA_b460oE9cO%58Rofs5im4gh#4nYs%rx`FVPUhe#0{s6Gd{AZQ)PJ%_EGBMv zJ_SV#A`0D=sHrCm;9}D&16a_+6m4qS46dFqDb-K=U?U4lQcuJq2(N9)%rQ8EcUPP2 z>WM@cWx5>!hU24*cch}8NQUqNr6zRV@UwL9&z4~Ab9yqRlm>CV(^2RmgQDUb!dH@S zu4ENFA&E+GEt{FVh7E$?@~4bRumdxhD_xZ-S>RQa22s&BN? z9Djq*$<5Blex#<%(ffow@?4Gh&d!)(=`!_*sV@72yWaSg^FH#MbE6?DDv2~ZlhBv( z8oIwn0iPT~(E(78dz;i{M_zJh?{~IH!gw13q3sI952F}JG2WwU^e*EA7dFnBX~KoA z?bBXb`^*`oN!~s$W1vcH>L2{Z7poklmKWRbRtAD_<({cewr_#&>CyuKFKA$&aFP%2 z67W`qGr_G2_@H)A`4=PmeLC5{{t zM-JA$Mtf>_lAL`b;T&YyZ&J>4`{U}!VHLkOp^Y5WoZR69wc6=@4F8sB0r^*BPZIsi`!-MLY>K+vFnv(_&yGQ5w5u8I!IIkm|-;3ZJZo>I}!g)ai z=cXncy4T-*VFc&qCLH=Mfcv5d&Mg6sNY3DHdRNwcaRbSaq~}o4cKUbMhwxq!!MlQr zH{AyBr4hWVsEE7T;5`_@+eXD~$M_#P^m4-}d!bUP3*Vmr#%8CDdbi z3H4ZBLOqt3Qjg^&)?;~z^;lkFJ(ibPkL4xSV>w)p2U*p^kP8de8^doNK8zh~BjHex z@JKY_aFFowXu?fF!YiT)HwOu?j3(R?B)lq`(2(lYouqnAC#hcBNvhX%lIr(6N%i_h zLb;Q!%AIso?xd@7Cta00>8jjGSLIH+DtFRVxs$HSope?1q^okPu3$v-biQ__(|5RV zPJ_;+xDNnV&M_#=>3Uf*KkDVuzgl4UL;DV?gENp|EarU{`dMs>UYS8oIohf z$i$O~=H3H8qlTywHq6kASFi+z=-!JokmdFoQyFN7qJkfb{+TlNqP1W1CYXlRm#v?S?}?yx9e5L9$f zQ9)s36qOlVa1=#FMF#~(Q9x82(P0!76%}{J5k==a=TzO>oeiCL{@?pP@AG}hbAMI8 zb86qK?$XPz;I7{lj01Bcg^5xhSjt?Et_;6KOu+Bv_MuaBmk92%@V8K|#~(lS@yviC z8ntW}MC=)HBmExgCM?AJUB8Wrzk%-Aw-UclMSlABpzuoIeLKOHHBbIzsbTplOjgEf zz~xtI@hye;Hc`4z>*G1v(=#$>Vnh}c2|15gel>o}tV&UqU4wbNhtV(cDwkiamEuB- zbom-|97%p6bH|Mm{Cho( ziNBbll*=&#logXNq>*Ct8RZq>xR!FETz(zq5+kAo%kMCTxw0TK)?&fiuSXX*h;k6W z8I?tG+(02@dt_wbuVy{irH2h%{)+1cF4Ls4c330d z?mE-p!<}hx{Y*pJ#E*X9QAP~Z8?K@IITUIP4>#w^GF*P*XPD^FhIF3BSw8s9BxM;c zN;95N@H^Ad(xW#x!X1mE(7N0kmw?OBW{5x^zQ4goP(L4jzwRTUp9lY6_aK~WS-U&SwaZpQuBWc{E^zOtiEmM5;BiKRK-o{2fXa6`-JY*n2cIjf1( zSep0}mtK(3S)lcr)r3Bjs4V>Tp&V2CARmf28_|6jXEjA-iC5=XMdRcO&cus~esC=^ z=j7&?a!q+9w5!J71!Khy#!^=>wiV2irC@J#_Sm}SJJ7}2KQlHO8enR3Bir?;*tDkB zHrK(Pi@gN=_z2(?9rn3$7YLhKe*T^JjPl08>PK$E&V#WpfNKiFkJU2;qj%D9jH2HiV{Al%$f+m0CE`eyC%Y~Z zacUIeE8$mWg|ZQ&p~%?!@MEJqS!hH?swYz;5sL{6q7d&V`(DC7k(<4Q??$dj05{eP;#}3I6VhbxQ$}jM1K7}5Pwt< zjpXunD%+>X&FOS3y$?gMG%m@adLj2;ko#LzEVpG;ZWn_#hE2)NNR45w=~(Yx6v8c( zs_#4z8>t>gjU)+ZQ`n`Mh@%QtB&4$)ydno%p&d_q81+6L#2UiC96eoU$ zz#blnp+vDd3iD42vZ?r$U0`b!bUA~~XDfj%&PLYAE+vlnCi{(k7YFjyNK9!$yzw3>=~$!EMVQFvu0Q1 zG{d;(M3EZ?f!ikx27$*$s<+ZNDWz z(9T|D76seV5>Nbfo)_6BWfka7Wgt5O%m-LC%p?~8+w8{v#_m-7fh{p0JId}>e1To6 zB728zCH4=+oq2j_>`GuG6^sFy0oY`Y>>toFk^O!ovJcsx-QqjJb|^SYybyxFB=QN{ zNxJ%6)O`UAUkQqiLEV?^aU~RVnf|Ez1{nJLOE&5hF4(muWGXOB*;Se7(wn0{#_p#) z1o2(OUh;5f%;3(x>ZeQTr>p4~3Vy%c#V+mVuR>?ZtTHbN@cfKa#nZFaCsmo*R~`3S z@XWqTiV&-#5q~O193PCBo{6|V1<^MjF`@u*xfwC41o267e+St^!Vs%6UJGvQo8z6T zpjqfdhU{TRft#fT&PPXVf(byiCUx~NY_8tm34Xq_O0r65F#7h8^+1R3)-jL>incju$c^J!T3?WZV zc^~3kkb>oTG8b`43YM@X^911M!Dj$R2LA$ixhoyp@I&c_km-GXzVAa$uZYE1eA6+6 z1|P)bxrmMc#3f|^JO=Rzl02A<_+}>JSSXD`c4gi*ejv}maNZn)cqj$&nJBLi=xZq_ zp v=@Zh}=K(mq@BIvn_btK-j@WKM3{es1h9Pznt^mwqw`co@E!d~` zy%d0Mo+128GU86ck14fzREBGd5o5{jAp19z-%7H3lKdjF=aT(*WRD}elkDG;`zo?~ zk$iSB=6Vm6VM7?UmMMUF>;p9zQ|J*KV&Z!|!vS{~VgRr9N(7up_Gq34_#(>$eAg=n z@M~rQ%r&CK%UBG!kc|ht%@grcLrzFC+m^fEZ7H{SCTvqH z(2Z={Kbk9CeRFgsLDy$&PHfw@lgY%kZRZIlwv&mSnb_vUw)w>N6HlzoyYHSo`|Tff zyQ)szzFk$_r*HSg?+=U9H43fZd$WB9c)x6TW(tg0rbgZOA_nk;QN2*_%y|?bvvY#2659F(GRGIW}!{ zUxqlGWyXz}=pZiXb{sq7K!MN`2bmG)Iv}&vO$~mG7c}C8mf6>uLkGc{q(6h#>j5Wh zHpz%Vjg%V;n}Z)YEpV>aF^ikOS_B7U#KID5I2@>0d(87Y7OrfKO;lITTDb>D=ZhT; z=5EoP(wG1aQVc<_R?ZzJIu4Z^!5dvG66~eQ+}C` z+8Miq%40Y7Z4-m6vrWpAr9%$_;aGZRkm8gVv5PpNR)z z?u}^v@ED8q5r+WcoAT7VP~^eEThh312K{1v2&?g-pbUmCMliUJ?1_-9FH_HdrM>X_ z!AZch>OPYoVG4XMC$~uV@<;y$E1=k?$WSV=x7sytp>(?XOA<(jXn@NRO5NC~ij(97 zr(ohX4<&bd53gVmu^QQmmyQ&t8}3kp4G zke>wldUEyYFg+Eci1b47bDS9mAnlwd=>8P+y*Ov{yU)H}T+fUXYPG57*(9FsRNnHc zxdgHR>FVzMQhqZigfQ`}0T@!1_5~LrP&^S>Zl+&eW05_gJPteuUkT|cBF<5boJWWF2Faq}=}_Ag_(Xk9hYA9as=LjC-!-Q?(&9xtcL0_V)j;!$vVqtj=MT$6oka!tzQ{XbW2a*M;6 zEZt6Kir4p~epSfIN24jlnRa_u?Zl9cC)qxrd78wt;{x_n5 z-({Fp>>!vH#V_GbmR5je%$B^Vyg&8Jb?ZRkuaj<0yVBTtdxpOU2{Gz;{Imt;+IwUg zPq`4Ac-EWoyM=EKSf(RtqPB}PB!9IW%%%}kf=MC_uslcvRLR^4l2^huXW~yms3xd& z34j(M(2RWfB9Oxbm925w5P7}tC%sgLnXCxh`WW-Vs+LJYy$1g)9|+!~Yx=GKx9Q_4 zqwt%}gJ*6Wd_ee+MiegnJVXCuooTKDVnE)KEI0YcmtoFsd6jB6z`{X;JO!O^y6!zz z!_MC1i2>ATyXz`Dd3G%U63E@e_s_V&kK4rf;76QarPy_9u+F_e42UT{1vOu{u5x}o zo&?e)s3OCi$K}XuIal3gHtGyF@D_gZkv%2DL!`V@KJQ6x|jbl!(xqHrVVsb(w!&apaP! zgfCyOIqY-Ir+TLw8k3vX>|>vJ2>kMfEu~qvN*le=5kx%lG^G(K1lx3L>nF$spDA;z z<5_P3_vENj&jqv z50T23DIn)lNOY4oepAyN)O`Y~0Tjh0IbXUJ*vz*gJIM zL|-?^F!6m~%54g~_&b%iP;=gC={t-Cs4vE>##3@(!s9~kd-wd9>F!>%fn3#yeP2dT zl4G-Hj0LWiS+to?{#@DMcP{SUjKS^P%W)%wPp@`{0J^vA(*jEF6mGAg>))HEO8Z+J z`ZsYqyBtm5Ht^VjN6zh)B>72rBp7A}&?%l{@z}3)oFMHocPr`>eXFO3>G9r*rVWn^ zy>tsT1AJ2Lg=m&F1#MyK(|d>qZUlWeiaVf+GEY(YFzi?WaQ zgOdKI^40D_~Y1TMPb#?CPbE)<<_?J*!80j;FNM8eN+`Y0D1V;;0BiP(>;=u}^)aW|kK{ z+vJ7HwN_Q*Gx3yfv~kmX=2&*(82V3YBXNH7pv1-}xumaK7sDHUrc1JJMb?yD&#ToO zHmLd5hhlVt%5Y?5y}60=`&RFJdoz%L!fEfkgKJYN z@tjYuto~s%&NoUzE{5XPW2^p$nO~yktxmcPs9?0(_s&8$14n9W;g6KQhfmld9FTJ6 z<8%l>&UuzU`o19pqV^zlr>QI3hR?12R7+&JTjKX&z6JXfYoL)9!tsv$ZNLDW zS7DJNKALbe<}CF`|Fk_gfAcrDr)o;)p-5<}_axsw5OA8+z4b{9*zW*5s2u3EUn)KS zmL@)Y1w1GmtiN$Z?`rP5QHe-)4+uFf>QY*bw29Q~#r~$QMdBMCfHF&my`?o6iT{36 z7I4kGJM*No$o{}QlLnGk=dGhl^22fe)iuKM3v^71YAiJPg*0gHB}H_+vQ7IiMBw%w zRGrM$N%T%3GL0(t;D1Sf2>HR13oV_ylX=dGjd#!Hw4futSn3;LJiHN*c1KIjBj&E-ECBvnE@I6+5e7n9GF~&XC zHpA)?6|zd{v)EWkddqjenVxSq^$T+`1^zo$fOIYC+{1GxY(^e4wXcBQ!08q#HYyNy zUsmw%Sk+X{F-7Sf!oz%hub2~}`fev_Z-#TKm|G$A!$M!u)r@PWg13~x``|c~PbzxR zOs3VUq~8OQQTd>N8GQEiPfuw=?D^Pn?VO*k^i^PT(v`r)>);Qb{NU zG#7D+ikmho>X%Qf57Fuq;+9WB7{7a~v9=6?BI8vCGkf75EVX%KG_JvQtKIi8_Z`TY z^a`~kN9Y=Vz`k#GlJkqL(gCneTP11eo|FmB6tkV86jjc6qJdf|Z*=?$E{=<`d-W&i zF>)>Qr&VK#52R~>V!?I?GDI07b( z;>mwL*^W!ZCw>1AK5_~t!(e{&Hgl=>NZQM&Tg6)!gEkn^{=gWFaBXOzp7oV ztyA0RkZ+bc)rt|4$v0w^<7(SDEbB*2E8}ThwOlHn=~+5F{auSzh@WFvoo)hvO{`W} z^*4EJRhY^$>9%d!)r^`U0+7CMI;~dFqI^1^m2c>69y6<9PIOzXm6v31c&2IA)nH_G zMNmphLnXj+1uzTQi{R-qfxej>rSY?*z4ui6TbC~FKarJc^9c7a(&q8o^6*5+H1=(_ zbLJI-3esrWm|->5rO}UB<>9nytW-+pR(dYYR`u%6QN!@55bp5#my@6UIL)A=={ENE zg@c;^uXbp7r=La@@-NB89r+~!DY>ISdR&PI9{{b)I#fsdfnTkoMU;7Ip^^`i`qn!2 zULy>hup-aVMWZ%f^VCurvzq@F^_s7-ibPq=`@uHa&%e|2Vy*HjmspInf5_bbPIoie z!x`jv2%>z{%mPM4S4tZp|LB!JZB{m?uVpZ#Dg@)nxmpcYsa_@_X&F?eyi(pVyr)&G zdZ6h!#4>JTx669Vo_*;2OL??C^e%rbw)U8`J;W;a>3)*)NWBeT>{6+M(O;?^F{ma? zW*(uMO!%wIN2Vh_4q;qM*}-ao*Y+mW5Th_EezkCG44ZB-=}U}A!3(07rNNlqfvP6DHY~*t7=j3Pw~riMs{ipG)J11;c>lKy)dciNWE1^ zLn_dyYi=8+b*@@%b(Wm-q$&2!sOelXv3$hYuCPH^SNHWasrNH*4;3zcpyTmV zt7hfP_;=N@O$v9|PU5I{&DG}|V;tPy3GeAi9a?o(v9&`VMH@{@caMf3mT}8mKfFrZ z%S{@6VdW>cs#23x#4Kjg=@GQ&q~UM-5J=_x6H$mR3vmfCte7WN!py@8o+|pm`I=Vg z!^OB+fEG^XO;%|uyS)aaO_rz!*RG#>`tkYxJ;ujA4lx{f?Nl7u9>Z98PZPo3nGb`h z_#pd&q%yy|zdrhUm<9ovlMlctG&Jv`V@C z65MzqH0GF2ltBfaNj_Tln-b4GOZ>bf(D_@!J~L}4^D0HJC4r(GHrLU98@9wUSs%(# z4+hT)t3tyt+tr{BvK>kk?)>D{VDneR!vo@AUGMB;g>l~&>|Q&POayey?KAhZ3DD~c z(iXdC(D?zNC8BF-?I+PRn*3}Ak%rg4?R=U>u-r}d_D;db>;HGR7d?(@xRz7!tz>w3 z(8wb4B|Fk7$j0=oIlQG6O3xw(zh_zbA>P>YNM~;aFaB(jxTo*eKhM4_3C&?AHpXN| z3UhZg-=FeL7nr^(%#iH~yc72T+>}RK+d>ylUg4d_o$wTSP zbwb1R(1D>2Xr3lkWUUZ60j)xbH1AgpqfkPXkIY0X=iUFLA(I!nZ8W~?5|)Wn=lEdC zm^*hDk8MXHNrd8_kD(c^L}duxJb70XPikK!)&BcP17CiIuTh5@TZ%Eiv_u^2;*^(B zUUQFGHF%sGI(O#5(#P&6EQ4D}%#H96@^~8RdvE8|7b`4SFRE~hHECupYFhsjXjJDD zHx{+Ov>z1gca@o=UDC2ob59%aH!Ah)(l|3MWdXkVY#6PNJbB_9O{HIcFjJs%N#*N6 z+ZJTjBFE?-&(2&9u6h}v%EsYAOD;-%Gvs`ZCEVQVN0IHR?W#c?+vu7O-Wv!&)ASLw zVVPlB<8u^Fx#Czn4S;f5lSei!aWUJgzFn_jNrvGYi%NoA3&m;HAht#v8c2SxeUQ&K z+I>PN(#vGfjEoP)`jT3b-)}G48&xhw z)jB*GCmN5keM%qldWw3v+%LFF_^v1qK(je=6vMZUB_FB|_M5E1uru&6Vj1mpV4**g zj{IJUWCT7o6>xg610(m0cTAB|Fr)2kebTTsSy16tu%1K7^`1c57 z{7K|VHEKMv4+g5L^SXctbF<`zBu8bVG*Anr+dTih#F*iatY7YpKQ-Aui)3WZm#%U9 z>}5ET95vi11#-N|T?%y>@Z{duZywJG$JQ_cer!}Rr`o%b+dnR5QwjXqNpF(!6J>WZ zm7L!^6COjMrlxYx_#|7Mf!C1m%g+c z55M%IQg~F5oH8fSCzOk{{q@yXNLbK!eDu<168nCB&VKLGoaat*7yQpVuS4A`=VS=^ z>nmHhd<*aRY)Gks<@`esm|Veoh{mvAx`G zV~<70l1E<|rAH-?jDhK8aM9)&_1O1g;>XQu$5dvHWS`_bmBJ)RnJPx@%qHnDa#IcO zr|{`2q^21%ee{U7qTa9o6hJ=p2<+e^4MjI`u_&C@$gW9Y`FkSy=rnAB^Kc+>V# z$b*9L`$b)moaYdgugOcqL}HMJ8bT$z@}8sTimA0}CEg&OIG7<~`LJ zGaJcf?3nbcntC_^GOlaz8G^!2*O)|pf4AZ%z{h2}c9koNwsPAM=P$1Pr_w;*05hbI zI-YDnLpBogb4cN*)9t;8nsCVa7b1mZr5uxUvsHRmz^kBV_9xTs0aSrxlZof6GM`58 z%8Yl9hJdh_wLn^6P_fmAM>=n}L+qCc#FK|C|6Pqsn?2=0O)16ql+WF|W*$ricx}Oz z;?dUhR}LYDYti+f!LIpEZv$y1dRnODT`ATQA?(iySzCub8}0D!JRi?OYIv-1)9=xR zrajc*=WpqoLb;c0DARKRX?dTV4&)kZ@|^k=l1d~wEq!L)*3Sy<1R*IPI8hlZMp;(o z)J^o)9%dXS<)U2?z^O1d3e5=H!hX-~JyvQUS1(q_FJH-1$-m=AgL!ho`Y)f4$L~G0 zxu4};0Y2s3O1C}9Z)K?CR>SSOwbpm0ShiE*V@ySx2OLfBneI*7B$f9#)$geKY$#!u z?&`vg`L5H991w7uR;6_VgQ z6H^E&cgaJ{)wnXD2304aU3IvAyTG!gwP4kBACuZ~=T=mYt9cX@CK}~Gc2aQ^Gs+Kr zW?8SJ9B=fTw2_UrS#FJ{ybG4CD}~`LwMx4wj~^b>vK$6k^gbp{a+hlpWewlMvyJpCJ*zL^Ux9)7hdo1aay9u*-Qmh|DIIz0 zbM(Q%NFXmT&tzkVBP_Su2@7kO+sg6WT%1F;&?EfGTv=Vz*=Xn4xJ1`1MMq*%o^U~} zXUs%GIhkT-$&UL_{YbP8Gp*5d@!|^Qa(eX&gsId>AOx0e5KQYwWojdBTwfAx1-gnr z&k*z4f!nFVmBACm(tLf`nWM#_j}Xh)~-3SgfCft5GoaB#b?jmCf28hwFk7Pq@_Hq66c@`bh^46vhHzWx@g^wFv?9K=&XCjCz$10pXZsIqP z?5G~&)Os*Ck?Y_?IF|iVU*|evz9aNyi(luX`F<9nVZ!Z-#MR>+SvZ|m2KcjiPJxTZ z=RXf7Z!oQVI;A$s#ot^q4(V^GMZ5ksSE)ca*xRr{vy1uwMC5N~hvmPEcfqVs_AoVl z3Nf91HXVH0J-<6qHpvm4+Sb=vndz-1-HPbl(z1PD5az*IzaZdjktd4td+uWdO#sik zv~6x@{R1XGR*0I3w*SsGle}GlK416n9k*XT*TW1pq}`-9^6jkhAKRz??nxSeLXrm1 zZ-l)*4N^~to~a;TCzLp|w+&)BM$c99W`8CFUm0@`8g+t zmO2;r-lOYZHM;Cr5@u{6{nkUW^z!7&0*wUC0^xHH}G|v=oy2X{|JZ*v^chJruP7U5_FJ0a)y(7L6t^t=ggcsX4 zG+6R{vi=8;^#`+}hYlX3ys|n$MJA0iW_5wcL*Q659 z+OvB;uL3E(8HZ^734OTK-FP8u1gU;Vzq2T9YOd`mQ|S{K+-R& zargupWc$hE67elph~#=sS-|w)R0YY%KmFeHqV3u|72-)>Z6Wbpquu}%KP1Y0($)OM zk^EZAUJCVoCx+tkh$Yr|fJ?P&@eCbT{JvH>HocPcXW3;@`<4u#EBWjvO|dV{p()J( z55QAZ=(6NrsS6TEoS9C(A0vSYnihc5Zd z7LUBvE!!Z*IbRyQ5s=vm=Q~|8>rjFsR$afIxXD@-PU;H zrR1LXg(tu~!=dOi)}#z0(|x+Cs}x55NtbS&q}u;+84E0KPa1AYeKVQ^!uYCb(tT;` zp9_XWIa{fJN~Z;QyD=8}ZVYf~Mjk2C=GJHSPmrV4)b|zC!%NFHG~EaXwA|i)s^Lnf z+Z}3Cz6=p`TkhM~5{%$>8~u#k^(n3_U&yyU8uWSPW27HgYVuD(0HY zR?Q5zD`4pKT)=Hh*!TJR@1NsG*puFpu>Uy!;NshH2sTpx_*Fb<4qZq_JXOE??7sRu znZ7D379=CBYX2DpHAjH9{UpXnRRulBV}xb}x%bKrl;wFQ+FP^{6hKGN6PqHu!XrW<} zbmV#hnI**$9tf3`3vOq_Sk2*^lyS_Jwf{Kt-Hi}yp$*sDdAV%wiK&S`>8b?p8FPfC zAb0Ocij%{K^WTRk$Gs=V2+fxn^o@MYeSi%YF!P_9PP~zrz{E|5wH2Q~-38-)aO2{{ z^!%M|#jVnI4{XKww>#+|z49~-Dynz&9rSo3*>&mnJ-894Qli}_qGrEEX+`HZ{;Wjk zdLgmz*u#ckv8F7L!}VI=$w2g8&IfK|7#|#G&Q~?P^XuE zI3&*g+Z|MuRd?V8BV1i{1mrZ#Kg)A(q@C}1a7j~w$j$;bo-XoZj`4J>18h{Uyd?*4 zZ9ENy2S>Pn`4qi^uPJSm(ESyX7R*1vXG5UrG6PMUfJQag6dt^_;y78pCahaSCvaT2hVWZyzpnjOnS=3b_8p+JFD5r|9G7Vt~WOUR8v zL9jN|d1G@H6%Z^YW9Cp9u z{`9B4f}nX&A@EmmgmG7RijW_rjWf(m`i zYINel$C$z-H*Hc6qVH92!E(m*L7N@)0FS4tq7+Q%f&h*R!*oV^mmJh-Y9h1+ETefi9|R&Rlb*p^lDbksm80F!AUz8bn={ zw7>I4)FpgvJ#qhjC}ZRX1~sfo#i*g;1D|>8udW1;9^4}uF^zd2CdB__Mf?9*Q#LTt z(5J~j6dU4g5!bwAh!l^Z7NKr%uW+qsmt=y>`r*lP{d}Q%|B(ylD)B$%CjFOr10(K! z+7vBeq_dwHoKgnFU@t&AW>){6GL+xNNPJV{#ps=OjqqwkFDEMV4LDLl1@A-NekDiQ zBNM5YL^q5cY0KX-(BR&rl_*4)eCGKt!d^w!2&FjsS6n_PMjDn%7sdm+BiV+8S595k zmu-sR5oT>-PB`Lg_AdQPskr;X;>`&4(av1?x^ZpAX}5aPWM~iQnhM`9H2eJ^W(xnU z6ndcUx`=Z_vpFDyDFMF&rEmYUk`pDWjG=y^Rp4wdqkZ6xBm#z=FaW^S`u>( zTEc$z|84?>OqQw%C$D10V(kA}gP6LRB6gY$o@7~&=J<*O=hl3!*$(V|(hj}lUOJa7 zu2m3{NY3ynPPlFFpwU!0G=_)|FTDKQq!CfZNdSAslkS=~(sqe)9n8KxK2A?>A8uE{ zaJLlnYy7U=U}+}!_3x(%e~`}+_!CRGh}Sjb9fY7n&)N;eyXJ_}lN~gOaZ)e#UB2h` z2Jt;@q(=vgh{cqiFCg(fgl;4G^_Dd6%Y#98YnbKO$*n}ctciYwu9d!)zBENuqSU0r zq;!{RpfubGnPQ3R>}siWN$6~Q5u>7SV1{C|aMr9~#DI9ltMk~Ue_(=Rask9Q)i~5R z;FfsIK4T~7^l#(jIpf$ZFW~O2_pa$UA+JI!D}B{2U+ecuh@n6y@!iW1!*GWEBwIYs zmg$DY+u~CQ+oHglz=BWBBi9y*H|%rM3*)W#;<3eV^ll7a0za0A+~W?QXZ01e(b4fa z4hZKE=a^@!cC~hDX4f-pTek<`Pw?jWxW4yD(?j#Vb^SUwGb1t`5c}!<;r1r*j`PBD zV|4ln`#JLV`273dXKR47sCjQ>pbNMgWDPQq@LIHYD^Lk?8tMu9JIpYwB~%s!0R#&| zC#SQ?PExN$kYA7|tS~{F$n~+P60QSZN;v|RZRkt51}-qz1c26GpaT_Sl34dW()8w9 z1bkaqHSo#^S?z4C#+zAN>iMfWTvw;y z;X?sSj2#BEOE5vhpFBHHyiGlNFJL>HW2oRI7FXmKjUi1eD8C3U*+Q9<}&i4_OI2}>G3 zGo`Ssx~>|nyKUO3b*IVp(#4yPP{&~LZHI~uH+bkD*xxGHG3d-EAybpznqFik3_C>7 z+`R+P29CN&t6A&GRiXjhqMtcPLaIUCAZRb)CWNr5;E&Qe#6JL9kf}8tLZg^~3eeD+ z0bzZlAKWN#xuEWS))mtOYAvpRE7YT~uBTD5_c6Z?>w&L|8_NS>Eup{Lm;$^f^r5iV zixolXDL;&Ea&!dj=bfOah$95y1R@yCHMw;)1~``HuuCXCthzQd38MDMh}rnFq&y!B zY}IjUpqdxgj=CWtu=gCS^yUt%^o}l&!wb@w;x`I#kN`Z}n`1}bU)Y$Z2h16|2d*x` z2+0e}3A{5)53F{#I?%2S>snWsYh-`uG)g0QuZRYOYvx1x-q#d6FcRe&Xx|^t zL^~AY_g@MC0olO_SR;^mK>H+4O$e>jI~F!)mkqsctdP*TM4D=cF~PPMQOGu5WTn?@ z6Y1X0LUDP-(e$yN2qaTBl#p*(@Laqhaii9sVqdJHQ)I7_hFimC&-pfY-M&i{BEzKK zT5(ljR2fCgL@X!d`0uH8gmFf`7Q5D?_PDeAI-0eFU_EXkt}?ENW6MeYrsh8H%rE~j zS2*Ba=&VE7S#M`Q$O)>3gBB#^fqPBmp*@tAa!_8Eu9KABZ)hU+J&efM;`rhZ*ElZAf11GaDx_=Vl83pgVfN`k7Hul1cU5xAwckdwS!kTE6T(D%+7H^x z#+iJUb)d17zJ^$Jg%VYMU@o0r^4N@h-8JcroM@~o`2G?t%qs^8u2qO}4zgv~ z>|^u^j*qxWH%izXFQzR!%J7yKu8*3rxnj@_5AydTd)!PnWAo{-M80&5K8>l{{FXZt z_vwhgf+R0~!v9`;Pwt*sJ&z>>{-B}{06&Ek`&lvIIK;AK=H(MDvp5@zbm*tx=NXeN zQ#om5+!{DbWg2C&s^^y;O*s`k=W>41O$Er@#c~ED9nH+YwQ};|l!#>!&;Ls*Y31}QK4qB_wSkf2P|w<( zk4>>`;xsG9W0{h)p_b#&$f79XQ_aepC#0IP|3bpG%;Qv;XZ&TE$SGIEr-b_nUl^>&F)9rb7B9ezU7`sIVsb0?m}Gjizj)ZdUVrRq~Pdd=B{(jE!QtWg%yFv3EBo%daDhd0*8mCAmA6d0)kn zJHA8SI1wMJZH8yW1Lo+9^dp9OLE0%T3*K6pk8sZIl-t&#=N8US=KD|O8o3>F%MywJ zrQ63yiO*k`BI!ps^KY_Q+du9EY(CVof+|>vjHk_{S4}hOaT;TuH9%-0@GGX8#e#i# zs)i<+;f1m#yY%dHn^WOKAjJWwx*o_C-ZtvKuY{PKC^#7$JMlR`_ztae@*x--d(<<3hXLf^&QlJJN1mf+g9RCJfFbSksJ9&p?8 zj9JRf`jA5HsEb^%_07CXb_IS^LQYceq=!6137phtbRD51Jq$4pxUo&##D>)Mg!n3| zp}4?`K=~v}yeWPJ9v`ADbGKnPrVCyjzzVgBwKGT9VHf!kjJWFTH)l8m+HvSV_5x~G zxPN>KAiRi-#|J-SWGL004iAAK_O$9Fj3uH@Pj`vCYg+&}K_ z#t*k<=re}x{JO(C{i}@)OJ3ihPT`ap-XRxtKmXce=%e=CGwQcO{|l^wb$7!v3_#MJ zM1h%v7KvFsH|~ahyD}yY6(oVZqi939`K$cymWhy#UenT>p3(|osEYElyT})c8nUL} z0?8NefFKqr!09hm7*06&Qy<*+gusa@Phot`(={M9(kj||1^j~n+ z%XD2t#x70&CXLKbX*rb|Sy~=`1Oa4Ppegd>_*MUUX9bM)XRSFDl|sSW>hZH{-Yiwo&^4w46$tN7!2j z`17lahd5~xrs{Op@Z0&*xOH(JbUSpbNwe10=YkY_`KOkbsHy>}57Ulv3B&qi=z2gq z7g_N`fhotUS&&*)?gOzx!N`ikDFnT{8lyql^D;4#3>-eTCplORI3o+U)nrTUOXlR%U{(neUU4&U}=EFFJB~p6Xlj}-5q9$ z!UaA@d#mk3e2zUu#zS)WTwwD@h@>wCb?X?iWgUzk1U3aQP-Ok%m)_b8|9U;O92=A| zb67z7JCnY0JZADJDS9J#um3iBk6g_{Ma-h+F9g0$>fg3meKlnbbNaCn&7>L2qehn& zcxWc3XL$ziR@>5)m<_RlJDt{1l^S?At8aff>N|r?PpFU1Zj;{nqsPb3qWgVg*?NjL za*TA;9V#kld9=RbCukrrf>#GCD&6u&4v)kuZf)r&6riE0xSpv>3S=?U2Z_Vlv#OG7uVnK(F1Q%fngT@r{?Eb!ro8vi@NQGcjg6WMMnxSq%8;#yzEddK=kA&RapPsIszJnT;f~zuFVU@bPy-2Rih+%elEF zp_Z*3n&fRSgZ~_Rf)`Td#O%=;flD>?QuR9%teZT~!Q915Xe(3W7;{UvZjwm>Q0SFL zT?o{()JSTI+dHlNS?1H$?i{8cY=o4tP!i{dw=Nxh64Y2&r-~V78aSO{$Y(qVpw{r2p8HI-BC=5?BjGo*j*spbC> zpGdh@$2Is11b)zGwtR@|;{L;F=H2+AmQbC%0r1r8kX$@o?JbC7mBa=XRiGmvSD~0h z7K2?<**~;^$HcbR*bt>@+VwPtQ&+m>Y@;aPhx?JDloc&|nACy-U&>Cz82*(ro7jQs zz|&fp8bp&arLr{Am}$X$Y73Xo7F!HBs_J(8V%gBzM|+uKD#0?!Y~6*&_N;3|Q^xH_ z-5axrD>Vq({xIh%lk>F=wgN=;8Xg#fi}+l#ItbIeHMJ!*bcklj>ctd;EMd6@`HNS3 zW;p-x6C6$T61KGma?`fCzY9z_{kuCyAHzEmiM0Hc&|b5RpD7&7xq5M*mbaZ!E@t?0 z|CYZLSDl7pFPEjTp3=x)?edEwx5?eEg?c4EuDQL+QNZKKAFcOn(3u`&DqCDFD7ngq z(_x<4wIVe{t&g*;sTdpu%hmk69K0$`Y12Z~DD%8=J$LYQLUKxNSJesjz7<_11Ir4_mKh{Jb?3s5&F{QJ#BKDa|XVj+#(0jwHHg z-MN2oQ#mdRJUs3ExemdTKZ;f2`)87=)KTW*w_dCH*ap{X&gC9|DKB!7X(q&k@<{@- z!+?H7*T7j*yH#gpoF#!=gdV9u$O88m4Al{Jt>Ipi$8Mw$uMC%R5=TCDg!(dIs&F^8 zfbaleS-uS}Ts65Pst>%^ePhk+{Id2-1!)vb2u#EbKhA&q)!sQ^>C)E3MU?g&FJ__+ zaPNJ=!_JOt3eU83X%T?o#+3a)vWu{YvOW$m%UL#aI(Gn|XsWMuq(1fk<2_{gxxZiO;gPPV2&K@NQ?yDfoW8B zv8fPxz5PkFA@|1*gub`cpQ{xncISi(ap-3E!#$_m76^##S}?t*pT~l}kps z4a)emX@5dbGNHPM%0Bc|!e5wwOo$iK9qzQdhIWglz=0Dk_AB8%fTOV^E<0?X(r@LX&`q{bD3WxpPat-2a&v4p_YfjJZc$U(Z< zb0C@!IwI29560v5CI^|WX1nehjF=?udcH(_U1)fQX{hfNQLTf3|xLWD=sjeivV~Zn*6xcW5aQJP}fdv!{%B$*iSM5 z7=AfkyjB0Qbu;s?iG^b1yJ>0aHHJanp*`){fb>fE!+x1U&YDwx{d+_LPTYnaQ;2ky zMv%~;3sP+z-)_q{T17#9H?90vl-ZB1R#3vtb4>S;nwP^RtB=*0(`KY7|ff9hf)A zO+ir9dnjz*m@jhdu4bjt`;1Rz$z;#aU>qiIz+{lh(F%|N;oe>U5*^SrMO_4Mpy^h^O5Q2VMj}-WZqxb~svow(n5ck*9Cg%?jldd4zj@E4s z891xNTw*&8z7=meiONtg7Ui_}mg`tkTzLEfs@j~MH3%@|AGZ-Eb%1C#@vNaEf>$5_F<3fm><_X9heBMT#&F=+I~b_ZbX zYXHK3h&1Dj<-_5_xjX@o<6)`1kaH-?FG_9Xn@wG=e=}^auJGBfzV+%KlQV6$W4(BC z)DScs^cxqTicQ)W?Ad#0uU8!Yg0P^$bd|5TsGAwWN=Dm*VrHl=84;g&6Z4FBm%?#G zkkPoD4ZGt+EJDDRP>i!Z#&~%ECrW9JB0|wjUgzr)K0AXDbYBE*W=Tx~*K9hvckrAi zFOw!%MsnBKd$h z#BtNUnB2c}1V(raP_C#_3=L1PCN-5#XVp+6ZO z>~Ws-v%^o!iRU~V01NF4Ue)L_-l*F?ChO?|RD~Kfu(A-)w%ln@W6b(znxf8}mjz1l zgqO(M>YoNARwK93mPZ@v!Lq9)5Bxh#16Q(*vdAji{G5z=Wmj@Mpaj=LuDPSiWyl?s zDzgJij*x9vaNF^BtQaF?5`v^8ANN1k({4d%)FiwqXda?w^04YKjZoMh)#*C`qXl8M`;Xu6aMkFCvB4^dv!tvK{Ia}w$H3+rU9ap+bR zYc%doCuGT@>d7mON71R;PxY2sGI(0IVE=Ur;ak$NxeBHmp&Ll#fi%Z=u`PfOUtkh* zA0PWkG(T^SW0~DNu@%Kp)Fqu0tKJ92%&ott+#lUarF{N?xy^T3dfc|zg}cH@7E#jZ z_Uz^+((9sFDa!6F#67h-(4Je6LoKFedI5KcqA9%6$LNeKtbnE`WM}uk07XE$zX#r! zrg6o=tguIvn`y_u8*Fr6!QQRiU;DNDZ@+q!4^x-JY3agI#&vrBYe)G*d!mOMhSboQ z2b>>Cv6Zn=RVP)gce=aL^^{I;?ZZ z!!nI^O4BM%O7N_}!JO?qR;#owwhIfjT72*VTXsVa44^_@=fK&*b&IXsA>_2W6~`eC zdCa7r$Wh~bsl}e7EQ&ZgMdsJKQ9q*xdz#?tKipTX*>|$8eHQEs7&_@o3{*VD4_&Qs~O+}%xyV=_b;!~SC0R`zyErj-*&w2h6_hz8+ihnYswHeuk*gbxda*lp0qTP(-dO^U55lr$2Mw2ENIK8Dl=@$*#ffK&U2T>gIpZ@& zf2s{)lIn%cTEx8}23xkChIx2j-`XZtUd(~#QqWE$wdywgR8=?;n*u3tv$xoVDV9d( znl7O^<7f)z=DO_E?aLjKS;Zz( zGSP={_1oBPo9C>z&U3O31Uf7w8Ke74zu`F!aq?GXx8fsKH8$t3KgKc02kftL8*FP8 z_Ua|lKA>lcrx~aX5A1pFsyfFIPE7go&fI_wJxD5_@*TplONvJ|l!t~MO(YI8-MkI) zFs7!}k73CTv=S6f#fS$E8FtutwOhKh8&v&of(>x29i0A}7-_PT z53z*SpDoZ~w|yR_HgbeD^Js4lVI%(WhX%MoFr>eeft zo?cz79d`YeB|D5MxMY{lx&GSda}H<21nl+@?XLyy?sVLQ{FWA3s&q4RlC8_t1@Lqe z<}XV}O^4lrivwE7y7uAN+B(V|gS4U<_7_vEIF+$hLYlI${suh{DWt0W^;Hh6i*Ra`i^!$!PY0BDEge{YV%s$QCeZB>a4JJ-6*-Zl+#xOc zArRAgxupFEaw!})!PL^yDeP6Id|01ULe`ez+h8!C*c}ea2W`1*PO{f^SvA%r=dQZ0 zdHBTsQh9>zCa81hR(cj1OHjL$NOt%O?Pfj9%37I?Iq=Ri>tf8`!IrX4HWye2W5L~E zqR#pMwD%rhQ7lWt@XT!9g=H5M$u6P-l4i*uNX~*N$$%nJkSIwo0xAb{7PFvYR?Io0 z$Ba2gFrt`I#Kd1cvkQxQ!oBak&w0Q1`3GjEt3!2nb#--B?aXvbdODT>e_7NQO)wKT zz>tYWLzzH`NrgO_=*#VJN9EnI94dD_#A5By_l`oKwrEI+hp;pHK9&KB^#goC5H|$U zP))g1x?00>DTG!VlW(HQ2^woD(mM`LkVFX%(c z53T(rj_!Y6J_O4EIPKSEP1=_I)4VLyf6ONc+5*xA=#_zGQ0+pcZ*9EEKNHG(uJqS|7qnlQVc+u%-(vp0o3m1;!@)ju>#65ynG z+2`kSJ_;20aaR2y4Z8n~M{%5jA)HC|>t~#p&Cg|j&PCI%CxvGSq+uREm+D2$w@et% zXlR`qHLgP-O`ao=!bj607W#*ocu{l>{y{d-y`*Of%14hz7^K8wc`_Q({SKk#x*Wfp zgRqdc^F~p6Wc_ju##8e^KAyjvU-~43EHNw08neM{F+0p2bAUd&1D!o#9(n&k4)n5B zEHxVvkfg+dOuPB43$FEB&_l0x(}4+Gj3L2rrUb{iEVziTNd@y+7(wXhusDQRLkG%p;S>^j7?Teba5;E; zv6HMJbLblRTtEzw&>A|8!NCPg4#DFwIk-5I%OTo}J#iM7MctsqA~lT5;xLqX0v?AY zj#OcB2`*1W;37Tv$Jl&A94XFk&*6#0k#tEOSAIu{`Qk_@P4EyxSDeL{5a}$pipg zB@R=yV1leK&fIz6DLjytt2!+sTiV`H;2x=HqQyIEIUJOQ8To_HTbqF>W4IGMW zFD{r#j|f0q2?IrPxk5fcBT%5L8clo@%i|D2x+@gvJ?Si-6dppz<+4#jbah}1APhKl zppWz@s9{2ySJW_yZWInK8+xmU>2UdYd(}{g5kMI_q`{>sl~JuVBrB@H;R(eBb5&5Q zRe*QqQh>N%C3Fw2TpmV1jE=Z43HU^Vg#j5gfV6}Pq9-sERE5cqA`Bb`-BG%iI@GYW z!gRGxEg=*KtOmVhps|J-V~x02Ml6as7)%T&7%V=pFN>lO+!4TFqg3Ex4udNWMr_UG zQUN|R4n`gRfnrQ_0D&E-QR3h<7HEV9DyTu1WQuT@G<;kGD(9jLUqgT@ zl}%+f3hUtlRJz~>6(;m>UJHQGt6^%mGF3(%tAr6PbVA4(kc|M^uLXI-6{3J9N5JK( zFuX(z*+m7&LJ`VT|PkqsQpsIGEGb)^{<-Kepq_)(V5!4(ov zSsi+WRX`faC$B3`&zK7>?C465IK``ov7ezy$EL)p3J76ni!8BqU^Vz?uwnL#sA(sn z(`1P-=sH4*en<*xXaJ>kfMXD&!JI%81sZ99^ggpNC>6;h4h9wBEFQXxSa9bMRD+-+zKDLP^<1>J za1njkED65xcbcf5nwo%B14bEm z0Yn?rfWmy3Igo>jWC%FS7Pf-c(o=+P2kHg~m=s6@SW#}Sn4=8n2tya*A9)>LY7QY|lL_$+Fl}{~QcTp-=F+k-9WC9-G z=V`)4pvmDd1w6ip1@nw0F1Q2z)70eBzytdB2)f4NqYD?Nt`JTh45+x^9Lxf^q7f{C zc6E?22@$o-0k3ddLjvfsNG7-0R9*&8!XQLK$i!9QuyoM0qXdR7B`kDMJOjdP4nq&; zQe?tW=j)L;LgOYxG7%^P@`ppvLPn38F*IM(6OlzN3TS<$b5M*;FUz=0a_ix=ki%*5 zMpg0#wHYdr7cF>8s~uvP2dxlfY6okvhFF8n$CV|)6cTF)QSZbWB6?mD&?P7g(VUj{ zASnoy$V<}^)Urw~Flf5SbO%qm<)h$6&2(3~GU~>bDI_qAxDEi>vguTU1U*}i!67Q}qMQfpYO z(F&lEk}z?E0%;9UJJPE(lqF26DIzo&5>*aMmYwEE&;nHWM4Koy%(@Ij&<1La2UN0j zn7%NiqBg?}Awv!{T3qmnA_7;|eEF@-!i>qXQA17wRiIvuK@qnT`R z!3U_5fwVvYC1#LPjvB?_0&}89eLyMz+^Fj}qy({`BUa)IfMZ7%D>DYXW)!#bBIJi!r*-AJjSR zWJX4t18B@Akh#Z4iX0zN3~|9Xis0V}+F<(z3pY;}H4QC{1eeZQhIg~j}aUoYeAh1q|^MPE-s6r*Go9ECZ0!4u%5K07~N3&V719T29odAm@ z6N&94Qb}o~JPt04gv7#)2n~kGLNJVI$&r}? z1eYzB2xtxgdn!S9QR_FmM2!_+*YT@_Q2Uc`S89LRD-}5q~v7K*n+Wt=cCakje(M$U2wg~Y zu|^kDbdjKo2D-FE7aerzOf4&DIYkh<6r4jL3W*Z(73olFH`2~`kbVi3IHME^5kX?S51UdYt9@>`J(UbAWk*uhe$T%4*`>e05rpptit&$ zgp&^`Je~-292~i6AOq+nkpMysNb^BzN+g$#l_#4b_X=njrXppYEFjKDdBph;hA19A z=Rso!xeewI$Zrv<6FD?+Wyr&!y&WuM*s&Qd?c{i zt)yWzXO(F05T%SVlrf?eV2BkV>H^}Qj#2_@a%p`QNZJa>lwm|`#Ryq;SHj=1ptMiB~50rh($QjCW5QlQbHcX zr7@B;5@iuiv;bThKiL*P`6GVvC;W;rT!a!C40N@v5XywIw;`;ED~obfh!QJ|2kmuH zf@MQaQd}q^6v&N>6^5ftZdb+JGHO%CGca$katoYn5ew3pxUlxj!az zf0^tF)39KpLb4~tbQB=u$@o#o70U4f)I-h!J)8$?1}LrY50e{ius~8V5a3}f zDu6-^%5NYJrm{28Kb4)qK#a$vaG{fr=7fl{l;!ah04&Io0{{vTcgS3NC?75_&qf|Q z4KDK55lBEHX-VKJEKPJ1$!;2ye?&tQDRew^5kOXG8uFuvgQ+kQPAce*5#nIQxW%6I3GktZxD6oOA_xGGRr-t`tm3I|(lP4TIZ` znw6CALL{RQO)p#ywzfr=rcH@VUgNY|f=1baULr@)^mA<~N2!36mqHB;&lWRPc5k)j zK}xoU+gkHnWd#6v0Pt2rza`A)Q|l8IrYDo!_LQ5p5{v;S3+V$47GTB^c-! zAsZ6#9LxidaNkosgGANKVO3;PTo;J9Ef>4M@g+M~dLR{HOFMvCb)+x}>LCB-WMTQ%f zhxky&Q(%zI7Xb)H*^d$5eu@ASK^6z?R>*1b02X7iA_Rj$$F$;PwyA;L2I97X_y8%jAck_S09z5@Dgu1P zx>#-SaoRw?Cu^sm`1A#O{E-xA`qgm^6>RF-HdOSF_FTFMeFWr>!ubO?z<9&+FaC@+pO zEDSQg14wllLs0|;J5dgacpM{{)no)#6T=93WM$S700h@arn0e&C@(r!rV>)|vLD4| z`k#^fXLFQB{WJjxG^ljyCuk$;mwhG|nV(#w{h(kftO`ONSH5aO2|k4y)d4LMYw(QZ zs~ZZ*7B?eU+>AgcG?KLxwH*hDZU8h@M8#1#b)cNw{en}Q8DgNOgBc%6s7GW*X9Ov{ zct$-inuS9?dgCWPj{6?Vj%_iA#x&ky@L1dWMJeitr0^^YJ3>q>!E& zofezu2#8bSqqE{IEX}26fgyc7B(5QuvFJrEM@eFKc1D(?g~gDh?8KZH^VsxMi@5ac zwD@d`*!0Z!gglGv%=mbVSlieHI|tIz$~vC3wTiK~u}O%Hi?JaStP*0RF;=k&(Xn<` zmUcF1qb0OwmNrlek)eeO@(*8OXe%X5AbX<_y{N_v&CH3XV}mo%D|misG3j}-STs1) zC~|SxCSGWiJiXk*e9+!Rm@oaZnUS$1Jx!vxg@a^x63{g|Wq5RcmLwaEv;-pKB`;8?dG9^(D8{WLH$XcF}(yrX2K{GBUv`bp~1AUuRj^u156 zJO!#@P|SFjjbYWNUmrx{J`>KAKYUjl)gGT|DoM?PX_b-`V=9q-XV2N%oJ4=764^`s z&S~^V3{54$IWZ|ou>tYi)7CP#CXAV+d zBi!kD@v=C)I~4y8xOTz)Jlt17hlR53@}h9G%Nv{k--oaT+zGh*fmv(&Z$3B)hvUEh z%wtC=ZvXE-Hkt^9z5g@MZH@y}eg9hz#vVdD5dF`e(o~0$vi^4-5d|rSb^H5IcqT)3 zoj-dZcL`+h{?9z$ybn+X|EC{u<^o%H`}@xfyQA!X|Djeid2n6&B^^nY{9_D~;n7(j zQK=W_&2b;})^Kzz`ue&gAsxN#1OgJIZM-BwR*rg!PLi6Fl`V;hmqbhG&u<_ZJdzwO zNzas|#AjuhI~Fd z^ny^9Br!TSUXm*N#tn*&mVdm^9Pixnr6fr#-5wxC3VLrj6KDl1B{a$$C%w|*B=YYG zQDjCrGwD47Byl-t?UBUGUeH3TDy~B>RZgKjp!zI88lNVKlYM%`91r+u!H??XLMwKs28i7PSGaYoO`dF`m0X8 zT0Ohp{k{|CESczU{7y~CcfZ_Q(xLODt~;i4KAF3g9Ble3xjC(GAD7H{i+*#44PKsm zdsY4YPjyq`YE&2Rd$oN^xauQ@$@vxEoy#>dCcPiZv-;{axcOj-3EJ=+J9XA&1BM3% zqh&`2W_SZmU=0s(On#sc`tc5J+bCiXnCLO+FCm^G8OLo7emrn8Xz8`WuLaMf6Hq=c z$4IxxD5RH0+B-yMMbfHnB(Qp9dd$#Bx3v6TA?9%P2o5uskuVskyXm zqIpJK4EDeN2=R48+b7A$Q$0vV9z#nEIml&iI1ngen=h7T>y#5&E3P(%iG7-&p)7NU{J5%-hDzs!@?u__Uj)V z6B`$wFeEW)XmUzwT6)H?%&hF3+~IloBSUEUpcQWYQrK_QlaW@lFGjj{ngnyyx z|K0(FWF9)DJ#FcZ43jk*k1x44*F(sfYFv3`)%j+>j(JBvH{SYf`iQ63%i1kEuD*WT z>&2D^3l48onQ(7PUBM}zy|bUJy1eH29%AL14o}9Kl&kNYacI$mnahn%CxjU~Ol{0~ z;2K?IXQO1^WO~Z!Ve`B`lVUm?y7qq6%mtI~H7)t_V$8ZR`C~?@()b{#?}Ht9hCu zV!L=q4=?ZjXwdp;IvY11A383kx_(ilpJ4CJJHw{fI~4hp?#8}pEtneUIimLAzfAuY z_K`)lKls%yHWBh>fS`m zrAqDc*o*F>iYw31z1!3A$V@6|kUZIe>XNRFdU)YPK@nyaJ7i-(_Gzo25fty@&a#G_YV z9;p8QAd~UhRu$RqjYBsjZVW7 z;$yJX=u9j+1AU7t9~+vJ1}EswIYY3lcu*T-v$3@FTr4g=77Ky2K=g6A98lJ&4R&%c z@604DBs!bwGLyp>irZ;u>vig4WNKlF`2&7$zz;??<_7o!0lz=s@CW>EfIkHA_X7Mu zfZr4F+hWN;{HqurcfoV;b@+X}9pOieA+`~9gdQV=QNlRDc*ihe4pi8_99cR}a1KDi z8BR19JK?+vCmJAC9PK2Hc5TM6G`wv&WYhJ>&`#YLRthH?kSiG4ahvi!VI-VEaHh)2 zWkK6h(RU@G|HGmG+0g$4=zo^1|Nn0tIEEfO(g0rkF&=f7{6#!EeBtaXA+S3NV{nIw z)RS;f?4#i71=c_an0URw3PPq{5SY5XsC);QufHQaY>bH!SWU9Lyo>CvxC6cX@T6)E zr;ILdur|;evB-Q(00RXbovBix)VsB5V0EM@7`F7WndwA5OBMq0nKFCjXG|JY9CoI^_cuqN(!eKo)2$>U*2BYfRCm6kEo%)WY~i%T?BFhit2y-DQbvDO zDC^f^j;B%PVry^yxL$KG^^jqS7|9%P^pw4~oI>?A19D_imU$w2Qx#haH2C{;F^3d4 z3cExBOBMyiQ|5FgN?JfI=8)42`W6Cn+k+|-0=Z&a z+ytl;8i8yWsVsmj;BSb`os$FYFo(QoHdsJz4`pD86PL@N_M8R z>xL#qr^IJTLPJ6%ULiq_ZuZtvGi!HuYcmfw2PL&a0TK?hf zUmI_lC22dHG~3`DzE|g>>i3k4?~IqfUw;;Nf8L9&%v)Eo$J*3f>vEnIsro+LXX<%> z&Hb69`>qgd;q^{VA5|>g^)PzoIOUzUdI}@U6E7sL>i_6b$->;)Wur<09_WwP+JE=C zZ*^Hoc#xgr=9BKO-qStzUHWa+oSmD^5BvPS0WW>TUN`W_ejDM4^O*;1IvI}__dc@r zTCdH!2aNN7Bq6t6%v~|St$wHpw=2KTon6!Wgbi6}wB}MY=TbH1yR3=xMJM@Cjqg*n z%*dx_=f3f0NURRMJyx+TZsHPG`vn9rI=-R^=K)1nq%M$DSIAUnwyQMm5gReck2}Ot zudCqOx0(vw(m0B>bPbpqq&YU%GzD{j$wubCu0D6*3fM=*SEt14zFz zpE9pv5A+MPqlHCmW{P=g%U4Fx@6Z{^NhsDLgWk6(%c5l%sn7nRK?G(shb&}YHW#KQ zi^ailW>3`E+Ma6*?-LO z?bWB={?p9YnmW54Fo@Nka-^bWOYXL_soEclT>8%Y&>_O%_1(UC1I`{hJ*U0?an+P# zUp|R<8;=^hySv#{b^Y4AgM1Dw7~spV9A397#?k$^iT4kO0~TU06ySQD+a^wgtW z4_|)on=^Uv2A>t@GJEztMoTxnKFbf*G}fxNHr_ubyf#;SsD00m za}o{h_#oYGgLJD>kZxPOkjG9B|`6U=u+)!Z)qRx)i( zNoiP5UA-P_ll;uoVw=WPRjj*wXzWprgFcyHJGV4_^}Y2KsvjrRB^o7lU8J>iS7m)j zUV7D8Df!#SMq3lowV$tdLGLx^lnU-X^j~V09ajHjwdaVdY6lyRb{?(t&Fb6}gQ$h) zt{A5hS1tPwH9Wuh6h3)QThp# zhIC1vq}X(+I@u0oWvMA!S~}R1RwmX~b`CaV8+ms|{Ot6l?dpB;Q+DQ7>gs!XF64J4 z!)bZfiv)>R1`@B>>tB+0z`DS=z_U@Ly_uEN3^fJ89q>N{QN$M7J_OWg*DyZ*wAu&#S zob{SJ=VPZXNzTPSjI4Ce<{bYz^Kk73FROV2w|x6N&3mg~tp{6k{)Az9mzUPvo~!OA zwazg0n75o5zShDy+CR46+tSe&`^+6YVabZI zyHMh?R#mN>%qSC+MXdcG-d57$jUR2*Rg2Opr9VowC`wxJd9%7soc+!;4%bv?0O6&Y zNPAR>D`tYCnC_(?K@CKqVz4p)JHEZaLYB>6uB{`IPJ;NqZ|0UQ!1uOORcb zGSCu%|D;&`D*?7OvtOhp8Fxr`;b4ixeL-$WN)PR8>1WTpeV+WiR9*DozGL<{tz8yn zmi5i|j=BdKT+PI8+eGjup57$!Yj~5mAuwQS#ew{QVT*h?x4w0`za*#R{JJd9vDXW4 zzd!KKcIBx^uRE0+ogWw_mTIl8$jl0V+hNY5Z#Hu>%dX`{=?(W9H^E;0Le>D*-XVRa zR%}hOxTPuhJ}cX}HrFEbZacEyr%O{~zMVN0TPpTlvpoZhkOcu$2n}YEAr6ducWECb8IIx&h zW%FdVNPC>gq7Z|&+Y(10EZ;6lgD!WSG`D8{;O=Xr>8qUf-!LOJTQapHm`Zwl>Jf<; z%mZ_4Bg=#viUzxe8RtIF-F1uQj-fAv7HMnz8ec@^ zyzJTC?7GKB!S^$DX3`Y~XGaCkFVG*j!P%nc-sNk;7eCC{w|o1i{2hLojXj>bjXhnX z)FJ6i#bSxsXF>3>@N;Gl{V(m$c)CV;Iin){!R|=`5%1=@FMj*}^{a=)9j%>qhcA2+ zVlbiG$|9ZFwR1SS?`nfSO({S9Os!&O&`Iq}(=+FG8yyr#kZVKEc505)J-2+y z0mH5NvEiP}d!K8nThTZC?jpj=(;}+j)}|{(mT6yC&Q*K#BI)Vc<)#Nunuvt)(-z$R zu>7-XS6;mRoVO!7`tQ3~6aMT%-aL)SQ#R^RcW3MRO*1>V(b`kzm8iWIHt?>^0R8Iu zCwQ+W2&eQ)6{-a}k23aMoO$tm%IPEZ87m@YMU0*^wM^TW(ZBKhiXr^$3fq@v79CDL z$+S~#NZ;Z#q^POS)~QzN@p{5ZcSZN&8q%x1uUzg>mw$}8{qh&n`yD4O-N65%X6U-{ zQB%#@vEKVQgMH!$y9RA`uMc{;EjRxL->2FewT>NJFrsBkLN<+=|aqsxDIVjS~Ra#v_`buE|`0*%9$);b3lH- zmdkJTMCzdeOy{4F-=rOBO@hR>u_BS~X(^>ZD-wbKoYDVR(tBBX%9i`LeP?wWm29qA zbD;L&@ddpNf;U#*)d=dW^6KL1i#<1HlM?X@&ehPl?fvFxyU*G*Ka%Wv3rl`B@<9DW zj!L7DIseVXvmMV^b^dM1yM`e;re8-sEzy1cG-yTn5rdG^Q$Ks1=Uo_7d113Vb9vLM zl-WbB8{P2^*<5_#v5~jA;fCT~VSSVyF-*S?g0*GjiN(=Q$K>5|%e z?yiv3KHI%!Ec37AZ<^h{4Fh`LysYoIw^&{k8Zlk6ju4UuVxEQT|5ta{sc5jXksaHgMF; zMi(#MurKf3+40`O z=P{8k>hmW{TxvO5mQ81+{<%_TlT5+M=NZn;6ZmTPkMg6Zy}7=-!;7HFV~^XI3|evM z#s1L(_mNjZGWB1Pr}yQ>M-IR{@Y@M5-D)@ggVUabzT30a@I@jSoB74!gSwxk8O{e>PPQ*xN=Rl&F-M%!wgir z<_etpOc~bS+oRq7ZQC{n4mr8Zy}2M?zhG&5GU1uK>L9I?OFQXb@TfDX+t=WG*7V8^ z%YvR=yZLsG>i<0a^{RUdmYjA>KTv3x%@)7P)jzbT=!jwH&MiZoCzj_%Z%->%TXkri z&l}bBZ<8!jwtm0g`{WdZQwax_=>Db}M>v~R_M5)@k^bWyn@`7X&kJQ;aWfCzFlTc` z-ui82^K!Iq&iYL)r;~-{8g5$IfGJ%LmAxK+TL0P$y}!+ z6)s2Wnv8#W45^Z$OBx!`3JIh_QZcnXQU>J(nNko+pq%>79<#vltH;2d8wU<3)IT?* zBk8VCL`iB*T9&mdQ2qH=ymGAqjX#=}KP(x{A{|eC%?&|mJvx_FPJ~j>By7JNXejBcz=)_(VS+%HaOo&gA)r$c&ua*pa zaDaV6oE(yC*EQKN?%2_SqCQ%;-hSa1bZM-*!Vd7>GLdcV*@wL?WMahbLXGrY?!`Nd zdu;!`vH9U**I{e=ZIUkNdFuSOu}_YYC;w`r-@x`IxJz3r?WjSdFhEHCN;wj$BFbp+Vb zBBDJ+i7B3&_K&Uczy8%hf#U{}8j1`jX#JrChss-0SW*?rWo9k4v$T@hSxfu>#BW`6 zJ~pK&#rC)yXuEOL3CT&#t-VM8AdL~P?1~CZ7q8Gw*SI}vXO}zgFAVtJwI*v{*wmP< zz55+Wwu>3ivuBpe$cx(wZF}Du)${wrP?s?)r}{VXm-km5{VIIk*$#!w?f59y)D4%l zBQFk)$UJ&1yXi7#Lyc~AH@$*&{%2o1I9Tmaad)|TnbUvb#K%rzJ?(FNau4Z;~W+;vm9bi4I_&TX0%R1CN3>9D1f+8ZGNFL zNQI~*^b3^=BH`d-Up$_{Bw)Ick!^mZLXMz6{FO@jLs_PT$G|dmrr=VOv(DTu2tNnn7`Xs^HgU4CY6h~D6O&arG zVQwR`E6v;;|5%_(kpEWExl7tx+bcMCDe!-(bNAw$T-ztb>utX$HF=MkToQa{M#k99 zVQV|_6RF_ORG%B}vbmo@aMbS?t#r5>A-g(t=%JA94 zhv+Zf*`Gbgr}%@@Mc!#;=W|=@%7gPRjxVXjojQH3oX0&oaKYi1FDm-apY`FSYtYcF z%6kv9M_i8bF5O={#Ax_}4M&7h_34-j{ykt&sLJVM@h<#_E4*)iG-Wty9!zAZFMcxC z`q1j%rp7yTJr#T9_3^t0x_tj;)L>nlzoFaJC~{`^N9~5b*m9a_AlI(P07XX7u81zk z716@YJ-PTV9lbsW51*-7l9XCfj$T`vHqH^>w7AE? ztjk5~I@sBD+L5~EbPh51kAK+ur6!x6kwt0Bif&lMy;105M%tN?_LQm|t)ME0ks)Mn z1y$MWFDv-T)BAH3*`PPbEg6EuewfUZ!o2LmsSsrs<*xP1J#Q#qToyZz9pIuDdE9En z%Bqygj)(ERFXHQ$T8UIvZy0dpz>Me)Po+<*x^Ca_!SJ&0?BbH|sx~v@I$caQ>%PXc z{T$;(p)5Ccl{Oj;#RkA_mUY6 z%|qQ)_VlO|*3bDmwP0V~Lxa_M1Gc7iZ0dJp^v;V8r}7_+(;3Xa<-GagOWQ+UoH}jW zw8zffS&Y?JR(DaI{v>yW+BUEL9@3&)H^y(;v$#X=(qs+=El9Mz})43jkUUbFCY z-NhHyKF&FxJJpA|4Apc<7S;84nbu&CM{a$$%KnVa)OGXwb#~qDIAkR!s_grX?tW@t zlxkiIQpW{XzZu)(!A3p^NJ%@=-jcL&puH@%6euMT_>V7A zMa0j`0fCkS0+s`qbL-!H&J^jGZ@iJVu1FMUz4zVDzWU4DwYw$P^$%XRn{BVf^xHeO zN=fgoUGnd$Hw16&k1k+uKIw23ZzpxXJW)A6?zb^>26s-WT}}jG=f)oeO|xQgSA+73AxWK`*c;cc)Fe&e14nfu7Nj>nKN?MC%!+E`ra|JT)n}2 z?*sd|4QX*Ud8^7|Rm?8C&i?f99!L3VWPXL8@l)l4Wop9@&T)SI<)KM`QOCe=qvazq zAE-L+@*8yH%W{)jX20okEYrNLGa*KYCW^^~(WYzcht{&elFK=Tw zZ`oQo%YMwIB?YD*g2HF&+jOaNNQ)aAvUjn{Mook9XBzf0il;V4y}8im(3Cm9?LVxa z-6cxHXy;i&Bl|A%9sF(2kJ>V8la9gawF&jn9f#H!`7MbmsqHfGvVK61KF4-MxO8T` zxj15g#Z`lc83R>%dk^3C39H$^fhdZ)eYpL$1KL-@0-idQtJE3z?bq1tIm+wNk*drQ z4>F&2zJJJj!SUBebs}z$n_3^}N3LE!?SB1$WtCs=ZceB@Qd&6j<+YaqPyLKns~N3Y zJ$gvNlSwgoQCls>UyoQEd1$zi(c71)RYucIr@PwqI#M&ibK)^x&*N7rJS?*3Hl}^b zlk_!J8#s9G!XCY>#^2gp(&66HpoV#y_j{M6%)j*DTFI0aXVXhq4(op5FKS)?ez_R^ ziI=~PBkCtFmf|v(Y34{sXL#&s#|o->zWRjpqQOLKvOm4d!AeB-Dhn(NDE9l8e$Rw? z3$qp`Ys*R$MOsB!T2hPMAce)Q4;f4bDJ*vGf6p)UC-}3;!eyxO5@um3SvZF*oY_Jo za|T&Bj&zY%N8svKf3>#8rN?GL&yrH3GxK9Jvdj~+Q%Tnr1O#cVXDQKDc#p$ebVjNL!E3YN(aV|pD}u}cW~GZrCFmcX$9!K zcXFTH=fdW1$q##Q%#9a4an`Q5vO{yt1LBY-yAoq9h$_wVPV#?ExUxFkHN*P()lPUU%GOZ^eA-S}HvzN|UB za^R8jl0^~2!h?Lh4!fUPlskZ5;G6s{f7y`(si{Lx^~q9G9ua&_TGSq_hxS7$*TLL> zdg1y*3sAwZEGs;MeAIGxfF@JQK#l*mU0D{2u7yra$?i2f^f#nTXpY(6oE~xadQ#o3 z-%h2UH1P}bJ8g0 zTCV=NZeFXFF2rUgebesdHekIenFpnJ*T=M(PR z8;(6I9I$!tea!`$mu+@i9q2yqRFC|*iPF9itS%=~YV^7~s%{P|S+dkD{d-Sby7|pc z(G2e`@zJrajHlDsJ$;``F5D?uaeCzAAp^XwZG1OOclY5hmo^=*(x{vrcx%TL`^ReZ0Sy zG)>x6$uvz)&&(WKD7n*yn4V3Hag5Hbmm|!S)s}eS3n6Xg?O>`16_9`8>L2cRlML=Q zD;iQZD5}HDHI5f=qLu+WNkq}Xc(do;RCJ2o(x~MtP4KDxeZ?XbXaqM}Sgyer0%03c zdr`UDC?amQE&RM`gjwn;L7jiBv+?_J-GoCty!d#5euH}ll$(?|vI?i7YBlSgjv_!1 zn8>s+mfI>CIc812@t=2yf`GXk@~=@t(P3EhltFHj+5?fVd`tlS*^*Fn)YRQ>d@q5j zRBm!sOjd4QiqfkCM|ZvbnybXYpA36QBGK72yP4N$cIgRcT=QAFnU<^ZoSzkbQ8)-M zF@$7ZW3}SMBjT)a>06rX|9bVI`~Q}XoYHCYk#$8)>8P)n8-3%lTOVGsI9jhVC1+LX zV0C)+;xO@UjxM-#hYV7g{(hJ0ddhfm7>tUo-ijoGVlPNv$LYG#JFRtaZQ>&06#kLy z(!E3seHVMFWzZU5Iq`itLsaXyz6-{pU@N)Bmd|tXTFMhH_kM)IA_*Vv-#~Mvwq2c~Ifz|W zZy)G7S1Jo1^07(SV9(^_2yjc}5mvr4?p@_NgR zRU}ZbzQ`SD=teyXNN-h;uN~nOl}(s&yJc`lYJIV<9Qr|09Q-MT+X`0noG%DHfGo6dCjn(XOSXMDX+R~Q*Z_289bO}H46`;l2_oAn;*cGehU3qW?=L$7SLA%zm=x{}`g~h2F|-WbK-pshwRa3{y5qzvWKh*}YO0DKqYA z!&eqXtLUA%*c+?)W_f=2lIkr7jm(fD(y2n*&iE34^I_5L*@(+r{kuhRJxr^Vqv}}; zcN1ItVLL(cDtuB)2XAhTJ6E{KWO&G7N!7K(0x_cbT;+DZRHbkH9U*bB9=*L_GaI9k zvr^OX2_hgY6eQV2v*`K}TzDd)1h=IUZS|G1EhdOsAL_q%N%ksr2id965c8&cnTl^L zce@_1C{>^5<8-{!2CCA93*Tvwt8Flkib%QH;kME0d9!g+tk)(LWkN z>gCQs$6%-ZMM=t6(U^a0XfKThs2Aq;?2DApbkJYo z#=oYUu7cX+6`k=#Xh462dzPV=4%kb|v+M3Dh2>V%=}>BS3({bAOMRf(J*Bj<-KL+T zv=lYRQ_j^^6O&s zj%hKMCN@f<>x|oU#P4z$iY4Y-E?6gWnHovD#Uw@Lmm>catgRoDuCU5}Nv6&c(lkDJ zaTEP0xTrBefcATEBLL{j%yNr}eTa~jmw=OuW74q_|$o7{{EXCzYD-?|!e; z0e$FG5~_*k#nx^$=a;~zJ$IGsjoVxzMV4`Eu~@P!Opo8eMK*UZ*(&voWBtXS)bV@- zt;8LXoC@8SAZdv6Q<*!nZof0OQyEdl zDL)~*1C%s9w_e=S7P`_)1Dgmn&bF0k#8YVt+{`9d+lM~^>Drb!7cAeQ!?YOXxf;!G z!w#jhhGMf=oJ6+D7sVOFG99|two~SB-2r^HZpZ$`8kzslpUW+|+S0gAL*e9M+rN-C zAwz>tX9W!X8~FH6uQkpW;^goP&qCG6S?Vr=Cv`QuuYvYuG@V%7f4R**>36>U*B`m; z3vI1oSETsvT0lF0|4yiLY}PaEkln7Avh-YH-5SS)|MRuzX}O!S*Z~doe(ud}S7_pS z%(5B0foRj|N4pN+7Q|_RZF5%Su<8%nZRl{!onrIkefCdouec8#M9mNRh$dqL-e%nB zHom@g*HrDK<8#(oq`4EYS85HW8iF`F_Fhi`d^HsFQKKIh{0#Cj?#0QxapOz|h3nMu zId@wdEb>GUqun8b^X2*^zKeXw_wT+)IWynTyyDwUHU80Pr(Qc*vCPSzS++K`dTR5u zUEk@!X8G1}3D31~M^KPKMQ};t_$mMT&Ecru@`KYp9Ls^wYZ`6v)VVpgRhiMMyiW5S zRCCvzPlRZkfE0XR zuwt|?2N5Ujfd))C@@j(*LQMrYpUfXPFya)V9tAY6Qzn(j%`1QNHSHEwdd>@Wzs6y~qPp@7fw#!sy4X-}kvIaozOMOw6#WU9 zy8^edkv!R5gp6ZXvpp5p13kZFx;YQAaf-^B`^9|YO0Zqp9-TNEe}I zv(A1a)#&)>g+F)T{THfapcVowd)BeRo@sJ~tYXL5_vZ3^M~F?-n*_mC`c_}fWQN^w z@|ds6er&!u903!@!0ze(B$A0Rb=Zr`ckH70@gixvH&>lxir#W7{o;(T%FV0QwIK0+ z+>tK3HjCkXWO*^v(|gujt@i$8AT03N98c0c-?>ZfBW1R?)1;NJzR2_Ckjk+_6?Wqu z81MYerDn~3Z_7Qqcgo@{*l{QM^eJuK_Tuy|YvihoF3Nwq&}QEjDfjBE)vd2tlk;?_ ztC#@rlJn)w!A9Ks$Oh{;N-_}RIkq|_$NeJxII*#{Y0k($+~F|*aX`V*sD1uj^Pkb$ zv~EiNdQQ}AX4k~JW{~7$O;>j?N43*Ad@iAVT8TyNIO&(9{~T$SC!<1fJ*nljsBNw3 z%SwOfkDq2)QhkPdTz_8gv1hog{esC$0RbZe004jkAOyzC>Sut&fdT^n_^<*15dZ77 zGB=>JF?Mov(zh|vcQ9h4rKeMJcXTqgrj;?awsml)b+fj*)||H4;D_%~z2L%s6{LhD z?*5BHP)uwdpFs*)#`9OXdk+wMz0=7xysqGB*yD`o8O0)y;Kcwda1~wJ_6NhH$JWHv z#f9hV`@7VIl_7e7N4^Bfs{%WCXkDshfCVtGkd{Ei|5T(qF9_-7-5PAY%U1vw%HzdZBKOv zTaC0{UI->`Le3L@k;Q-{K)1e7#5)e&uwbe=f&l2lum@)T;z;=(+e}dW4`4?m7$YNR z@%hI)fok3mg;hU$93mUJec`rQ1Y7_T!<8aG_Ni%I*W0{NDT`w^@MUo<*Xndn%dOz&d zXs8tQw9bQdrq*f4o<>mw^LoGW^SRP=-qayMV` zST>9w3^;C_twYet5$W~NXSEZ9fAOFLjf@n`(uss_&%I>x_p9)%(bN3ig--9!Qd1>Q z87!9VeVawJCUr(CaPy zr=e)o`?!i2unZHH6{R$yTPR3(Q_c+r0J$>RTio~Giwd{&ZfRhpm183XC`6<6CdSfU zQdU0OusA3HBZwPZfwRD%?y@$x9_f#;NzaY^NVsu*KTv1Ldu#rQm_OAFifVsy<5NvF z4mI{^MR3&|Ud0tICLI-`!J-aLEy`$>x1zXyQZi5+Zly4Q4?&tnf%Uc%LO9 zF&R5(BiR zJadwmAr9(~*FH4yzBIkW69N`AdU_Di5X0T6BsgF~++pDIZ+FFoWr?W@p={5uukV5r zPOVP2$Ma65s+g)S&nu|x9=mMNuj#DA)+on^D@5zpF3=sHu{Y!Jcl=8*3SO-Cb1+I{ zE3P{Aj=j}>is5GrD%@3Ou5Mdp+pqln+V@@C)b>`vI!f=-zV+e8>S$(SH;MYC6 zXTm>JrG($x3_Xo9R_jebNH3-3l5`3RKt_x?aPhXy52`CmbvsZxGuiTI3!v@OY=0TW zKKfi7iiBJye)H1+004Oy@UF*lVJiVbdw`A|pk8f664C{+5i$}b3eX6%Q1coq58qZ7 zsy9*@(o|1$xrZSxsaQnJtSWXy6r(^(IN1=n0k1Iz2PosV&J~dNvTsmTh{)Xe5ZMGk zzXkhJC`}aKJ8VU14+EYk8~SbTtg-yMqmbqR++9q0?EG!%6y?X zjaeWOJ0dcUSt5~=+1%BSi707;A}ZORbH^&C>Bv|N1XeBPWnu5M`oL#@;=Q{AAFX}1 z+gZqQbzU8{Uc?TQW;}e*=PnM5x;s@A80#!<5(t@6%uqrjYh(qWF^G= zW**3sGT?m3Ax}6|GvR<6Wb&FX94<%j=w;GV4!6W!@X5#cR^p%P)U{!Ye{*V{TF*SQ z6uz?XDIW1V*!CBTP3F!h0+adOiwpRf$reJg7EcX0(LHqO8dm;htMZQmf`y~bQU-c2 zWoYq!-$E4JsDcC3G&=u z#V&V5sD7X*zq1va8F|gn!Dzv=oe-zV7cMv1n1A(tynKWyL2U{$t)0xZjEO`!@p8mX zu^;tLl8_eRD=4QECWcKp9EpExEkKt25Bo~4e2cPTg}Xhh-_(#3+<=CVA=MNjIf6Vf z)#d~b|F*>*X50?{aKf?{QGP}t<`K)^%U_JlWQfbiSiT>(-z8m8!schjWb82Re+Y%Y zNF}K}Ek274jF6>lAp_mhPnmIiG|p_8hzYNzV#Y%MV)&C*DOoIwK# zrv8BlA0oFaeQ83INh@YfilU(TwpjVPdJQ9HPW&h_1dpr%YQNP0y?;pyM}u=DlVtg0 z<_u)66MBny{jEr(O5hWc-ZLg;e@TcqZU60Xt@$OAfDnMKKZnCLKyd_jC>MJTKKzqb zY($l4dR06={UbwJb4Zn`6T)D>(ro2zJAKuuLOMU@= zK(c&N(nQ4tlqrEg2+i0y03c2vh;WlNu)BeiDuZa3pIokigD{o@S#H5ZiJuABn5oM- zod>F+nyUB@AKlb!GWnIu>WId0pcu$kJ)O{?NC7i+KPTSUU>j|%o(I5-WUAvoK-xvP znwG4e#vlg#BOfld9oN?DCmZhh(hu6ah-9L2c>PZh0$)NxY}FyUC|^LT8QRwDg+w~s zHxFc~x~Lz%3B#cw!9+Z|$U>YII_06OCf#sTlTq&Z4;>7}>Kn^tf|57&S4c>+`D}lo zx;C%HSrI`W^7KxC_mthTb46oF84IR526|^QcyK=QYrsxSEP4Y6WrmEHVfF9$_c}Yu zfWt(XC-r(}wCTaDu4V&mxDs!6Fy9eUlwpSf3YLAUH+4H$qUVEY|Ch4IWu1Armqqww7nnFe8se&iwu>H5OnzzQ0y3$%pq;s{^^ zJjV#_Zm31I>Z!46_dxAD(;h9OXYs2qm^|%)fG#iaQcHzY!z2Kq`@`5c3RR_+AzcMC zekDa(O0F&Z7iC6*W*RE6>h~TsG2Jy>Xo{Jkit{+Jy%`UxG!*Dh1Qa=k@xX6GD zxe&SOp8dQ2JH&_EHYsK>e2h?{CeKW|{7}FPg?xTrjSI0`!U?(e3Gt^Y;R3!pQlg~l z-myy(4;XY97@8d+d<=dReMF-bG&(Uo+iv*P%o5AvO(ap{B%G+d;Y5yzhW1n+W)01b zfFrEl(N@((fEwgBq**?7q)Q2YC~QX2CrFxB%Okzl$#JnXenOJT2m7F$GxVIYAh*mwJLV9f(s$QjN1^xsQbbT|f!xgk zP=Q@lBAl|^DWzNiZxHVvHM8&1%jtx|?avdD)sl_XUxV>%@euaC5`NXnhk~n-soSe$ zpDB~Engy%vTI+bL*At5W4pWl-4d08c(I{Bvg*@TSlKT>YBvMRsmCB2>wp*&-!Wv*j z(;lbqWe=QnN2hn?2f%H7vIml_v>ED>2peZ#$yigl+C-0G(~5ZKANzx0^u%sJ9iX$_ zTiQf|&Xj6!qxS6JHXuCbMtb>hlDlO&PG-P5@jWo&D2|43odV7-s;_4Q?32-ZZA|ZgpeB`CH)L z1geqi%|v)MHTo>TJ2Dv);OKFR?9@<3eKkC@jV6pEEGd;jr{|Q1-umci&lkXm=f-cs z2}ga%X!KR9bajpnu@2_dIfrnP2SsG}>;HhbH!kl-CZI!&eK8Y!9><(am-Kl(_&4iH z6aGx4*4E1IJUgi3iS`GE*1FDN?PYoVL4U)+(dchuCO9;2iD4ijyZ^x1j!{uDFV+Pk zafnzUipg;lwmOjqR>+he(}m)0FnuBY-wHa0rDXcrtIf2nJM1ZzcAX{(*Fu97sDaMA za2^k`iXv~W6?^3V;N|d6hVm?x-C()2-Hk_Vb%+mg>oR^HOCf35aa$T0O`15}IsL>9 zowT7tuk}0KZhe%Ty- z?XN*r{CL?+dM-8dI=EexA+(u9d;oY@^6RgP2f#-K)Ov?T8)S43=4bbI;LUd5yHKmT zHnn_eE7hN3)y}&T7rY}EsBJh?xc;2mp~6&20wj6G&`8f+p-ebRW_gm>G$4@h9XXBz zPCm5KrrkJv``&&xj@6^qi%k8j1ive9UrdAEeh#PwH}BYuD7D7C8%z?jkXkq`e?%H& z&-dOg0TABSK+R%^_(4(Vy!vIN@BI7 zJ&x3a_Olap^Tr{1Wj|Au~$%MgqUwNj)**A-%{Y+bjcX#EMa3oJ6D1>LHkTysPq1KY}hG%ufKi)1s--rnuCYOwfeuqF5DmQv5)Fa zG2FRrd1od1kU;g9 z>}mqL4<#`p4p5TcGE-i<=NomNRq~6-N>J;{HKfX$^U(V6isRJ*h0AzV*UuTwG_=yD zho)Il@0rUZ@!8Q4%zD+spN<+DFax~MnTan()W1i;O^0(Pc+7t!ea!zwOfO;pTKR~_7Dj? zKqo(hRN{BPB8&jS9kqvSuCU@0lqj@eBA$^sRx_ZEb2F15KbCCxE`!@9=9q3T_esHq zB3VRq!oAZX+aR9Lx)$7tA%B=6e;}pHD<|&gq+U0^isIjxS=S2xi@F`+<%C7LI_HE5 zxA%+FHB2bU|P3ttjf)Qh^!d0}l7R9><=tI;L`%}{% znRAbQ4rA1cDrO%a7Co7s-}4*>n+KeH18*R@pJaa15TT7K9SR z(99}5%kh6ZhE-k-}K1(1rm8$8cK zt#gRQbw7bBK%oRd74b$7Q8*S3Mt48fpTa0>V!gk@^JTTED2# zG7NqT(YGFYQf*YUodBX%17GAkB#g4#RWG+WyZ#?%qgOmP%hg^*oL+lcXRjg6!V&LH z{i;BRya8a-Aco{*Y#d2Pnk~{RqXUbUID`WYEtR3*QEiM(oSNE+i$={0rp2uDiQVo~ zrFqS6d-=V)t!9xKwTm_y75q&D?wqxvO&jiQ7f-BWnWGkuJN5i2QQh7={{C)nalF{L z+{WD)&}4u<`5)Gp>&)=2Wn5XMGH?U2CM5fLnw?_Mc@de7(9_^ZpHG#Am-H(2-tqQN zU?g0vHf<`RO%k{1w`qQDEFNs@YqfSQu0G`tnV4%bKfnEUnZvbJjvH8Q*|OQu^Sg0cVwg@dVR}3Y+97bH2FPedTbeh&NAPeh*SM(_Ygt+Zld8?|?>_ z$5cPNvDec^6WSQ$!t${mtEY6m@B$8qQ9s3L+&yn9$F(lDwajL}ziY0~{yYMrk+#vv zy)z>3NyXuv*3sd`Rmpxngw<|IA79`BAjucf|1=FawX>6*QJzr)wg-Rc`YbB<{a z?o{G)J(>sKOa+2@B@u1j+jrpXR>obw0oQ`EUXJH*vnt~EwvovZCx0FMJFWz@Z{f>P zJ@j_sDEwxkFBsZZqOU1_$PdxB><gmolG!a(3!Wg=L%FH!Dk_D$dz}_j)G=O#(IPDP)hWptAXBqEW!oR5@v0|3i{P; zXgC2Wrqe?qI`1>X8_&CaO!V(6gRWZH6C%`g20#drQNcEMIgrXc?kI4;=co%zD&Im+ z(4lNHbp{bFYP`XDF?i6hoSW0MJIfq*JSoz8d&V>q$izMcgsWbk0fAm|AKowfWrv(W zwB>k~-Def@kGVwM|Ql(EA z4!0lweX-eVIfY{5EatHZ;`Cu(Oc|^rZot{1k}}2~#DgPA+k#-=2hB^6d46$#A+VlB z|46|pHh|WY#?BZ`Hu;QjndV<;rIk6*{c>BeRPD`8A5bKvtm+NaNXJdZe9e{e)9D&~VER&|1q+>1wHHQ2dn{W%Hn&NZyJ%+2m{pjJCdHPeOvWu4ZIu0?^&SK>x@Ip-#Kxetf8C5L~b{xuofZ3Z_0 zb4?$``S>I6x=;s8CzI7Aaz<5)vQDzTIhb9E8<^YBbS2EMD0F8mrWBIKqxda=Lq~E7 zex&~vyQyWq(M0e>%O^deq~qrnuDP;G1gnRWtsv|2INp(f3N@@QPNOAs#d9!4bkm;n zX11Uo+Swpmf%RusYJ-TPO1u@?n7h_vv@U5kqi^w&+kECPqk#i2}BF@MvC zKHBBMeu}xl2ZI;3dq@fPu;ll$mT(l*VG?JWEb%MxCe#Kka5CgmyXZ5Z{Tp|<_Vo5`R653N0+8zVabJ#jFbidZJ4`Sc_qX| ze-@04EZ(fSbr@Sg=X?BT2jS?*Vt)O-)8?8RzJV3DEf%Bn;=RPx4m8&)WOvZ1yPQux z$$g*>VG{oADx{TiH^0h>hKmZF%d7ky$rFNukK!21fvimYWqV*a^DJ1)NQ(4O)13&R z7>W*!`AJ&U$wdcIg}k`RNKOJ=qdgcW-05*hkP@VQChf^xHZ2+LF(w2Pg&B-jAo9A2;5rm?{L zLBUPn0Q&q1OJ!wMPXh;al2M7`ds~l}DRU}a@TA+~<54$dQ(iV4hzsKT>*b$If|fv#2r%Lz%>2=20I?{F4~H{#8J5G*xBT=|QTUJR z;kENRZ#Yv#=3+z9wj;Fq45_!F7>6L6g5yZplQ8l6Bd_1sUdt2Xk}taUP6Kcy@3r$q z#mE7E3d@6ag0xM4Yf{N^n4J%RXhDd&eV&^-`I?n+&5h#83^nAjK!hmG+4WfXN#tJRo6qGuJqSe4hFt?a?wi58 z;kV;dZVRv=y+<^Q9V2X04|sdDH-0$;sd}&pyznC67sLpI-dQt74E|}JZ*DsaQMkc? zE4$eX2L~dc{E(rQ)w%RPwZ?Nuvn6GPW(wqh$>s{amN1k9?gauC>o44%&wZhl}m@DtSTXfNg z!n|-y_l6$t3OqbozlW;-OcVF^()gwv>xw);S-)$l{dgqs&86^7JXk02t)=iyJ;)^R zEv4k@y}LohNRGw_om@=7<)^ZgP^Ee!8!1u=-=Dpp58KnDP8X`D_$pIpi2YmQLyb9B zRGn8RU_dR&uJ1Oi;MhH8z$cngFOMhBLQaX{y{ObjtSB1KFRVxuR!E}6szE$A!V#%5 ziX5{?!Fo)18$T}&peN_Xh^4~ILzIn~mB0K4Alc4C%{xvCj9ijHCfhAjYE!&c4n2AC zTliYdKmw*b8&i>srO3rX{CX*Fqnw~wNpmUYY@1Htc7?G!5%KS10tIKBk;uf7s=#Sc zSN_os_;F(S!?^zOWW*vlT8Q{E9n}Nor5uFxYKQ>fr_#n8lpIP9gj)a_W)i}mSE!tU zZz#EapP+}DAjx*y&3qnAJ#T9j4f02tx*WAe3+X+=$mcmn^y2GeylA+=o@{| zSI9qXYoM-pfm|bd8NfDWFgA37l}v4yZU+7E)DSj*l=fT$yXw%*?pnvYy5Yx9`63j& zZeta^deI_J9{+oV2sP&1TSL21bS);->C<5 z;MZ&ZtPOu*QvIQHoH;M9I42Kuj5w)lfWmB2IqoY39s^Ku6AeQ|&AxwB?ii{Wfo5K? zl|O0&$p17%)&rFM8Pp=s16x5x_ns9D>yAM6Mc0k7UA!mD6fSeu%AUVr3wLtszvP_I zS$3x$bXWD4c!nNaUD2CM)qcc76?6^X>tS^Uck2+Y)fo>!9C`a4>}p!S*snTj6_|U{ z^*yvh6<*;dcenMIatz*yteIctvo^+@xJ93077`rIAqIZpqDOZhlIHM2`S9!l>Asuz z$m!T1@eY^CM_;{04h81`SHA2P&XodZ>PE8kX^x<6Ic{VK=kQb#7gv8{;ik$Wy$$TN zOn@9N`@ZbV^mtKN=u5lQa|l*DV`p+wu^C9S^$ef2t*Uyo!*CB<7~3K-wu<0+OkU{O zll%XXBxN)(_3 zOkpGgla3hKJaSwGIJ-uLyQ*tx?@pl%Z~u91(6?%x(HC#^>{=Pyy6ab5tc>B&l)^ST z&YO!!ZqBaW5Aqdxs*)z|9DFXn=ifsC2kp+;zVkn{#7@pr?SnSR1MjHd76Szm^}>9B zNq4+8=Jg^>ZHJ@o*t zTjA)N-{FrA=X75QU^AKpDQmk_?qHT-4ze!&^NksU?&v<4?Le`G`715ygG6QG*2<8z zY2nU+=6`I-@jCTKZl#rM`x6Xj+v=cMn&;nldybGsvSh&4h|w?3(1>py>@39#d_4RL zUYiGV@Uh4S9z+<_LK{8@gTD)uW^aje;!b{~^KpA$!c=3TYVe9(g#c`%q~+}wsJi^a zs<;qUL1{LUMI9JvYz5#8ncp|yNVp``CmRLeODKcyiu(9OgTdz2sX{UH7Q3Bl__1EN zDRBAz^?cB~v|2k1#urG)J`8Naxeox0_eZ`daBE)n9c)5Z;k#^-EaX z{Lkg?tE%O=8?&#wA6!_ts7DjWCsT)W$R6~--u7Wzf<>LFd2hq`POuM4%uy`}evz)U zNp;`0X1ML;@;tp$S6TzSQ|G?X_CM-gBtKfg*j6%i zy^&kF%I5ifl3>>X&Au1Xp>bB$A_uPe63*sDZsf-M!VynE%+>TRP=OF?HRU+@A2l}B za7Y$JRl)=6(|H(EE}x!5eV7L7^unv5lEBC27f??=>P`}?`nw6&lR=ccnYopV?_%$H z;&1V}Sh-5Ed*%>eUg=*m)H19?pzeYiaJSNt!J=@rHfXF~INh^eID$hI(?o({amfWf zsPEoU$n**DP(-CTT@&#sK3Fu_@YD0Yd4IDMo10(FEr@y>$1k|Hwj7H>XT<})y~DUR zp(UDYMQXG{h2pG!;jwCskni+csYK6xWi*y7+`g>9V<9nHiBZkonq7Spuh-q9>d<*fvjgzm{zn zMXW?^bw)VEj%=IO+=M*nl=bRZV8GSzrQYWOs8}f5aho+N5snrX0=rmDH7hl@aHiA; zt4(6AqAqa7&(Azx#>{B)01CY-ak$y&1-8P8w4~b8S;Sp7iA8a=5e2_`G+iSYmJ}qo z@^8L`iQKs4-1IW>8GVS%>DZ%pkmCd*xQ9HpwBEb!8>8s-E&^R<0RKd)yrYd*IH6Om~Uc2oKI5ChEF#gQb&E^ct>o3+A zH{CC|Toqogg&IssEYoeGJl(dla_efVnDYJGcl+OrDHWKWHyhZXt|$!xQi6Pt|d zraW{r0R*y)9K=z+_NofcQ;I>;QqL<;ysNlh$P~Ug0$;jGI;XMSv4>Btqf>RC9-*IJc{s@_ z=P}=qW3kg8zz+LCEMM8|j#jX&ju_zXh)YTNV>>hp%2Ze4;;sdCA+5$3codAT7TcHP zA;dg7fp3z$df+G;z(=V$0h0N|VO#(A4)7y0OdN2C54F8w8_~1DYti_tVySKFJ)Y}e z*m%M1soRnlL1V?T%-h~7#00Rb#4qLe4N$lcs{e%Qr}^k)iJncG!L#;X(FoEmb6JC?F`j+LTD|W zOXHxQl`g}0fn#jY(LpIux}8W{r0CcheRrY|?= zv+zAz2eEeLx~d0Cgot(W8kVDNSDOoa%W%9YTBvv5T!ep@ZfN#$}Q8q-uum|Kv_$f2-+IkfhWplN>2PaOeoO)8(Tk z%ach_%x9ZMH@)i&()6SXc-QuILe18@qT%Xa>Ua6k$#Y)bTl(E>taaB!4y7muoh>Ij zs}`Jrs(J+3O!8iWLb&mQ?-+xaZSxfr0jK%}*<1=-^2+o<3Ea^}nqTV3^??QKX|F7= z#DAafRb1L8pjxT;%gj)tmk;^xJyziN$IrQ7rsZlBJ>*zV7iVoiw6bi+-c zxm!9U-!P|cqMr05J?_r$OdV;=8JkC?%GX)5mO@0Z4Tjbdk}NUSri6t}9_mVr5`T(i zefFdb!3_F2FysKipYu!8sUHeFb*pI|jWY@8#!~-PtvE_x@>pI^5-@~(=V>BlM?19-;ZH#CfkAo?mXXDFH=u;qD zNmbVWC|LUq%jyA?L{}s)+2A|5vos9h)Gc+Dk@l`QQrr=>>{J04+4D1;Q6LPAQ+vyv?;-|8lRm7!QT>xlJsl&V$sm)1fR|0n#yK|^= ziB*BzKIJndGRJuxX@)ZczH`Iw9*fFfehGkIrf)egPi2COCMLXuPV<*}vY4RNEk!U; zRwqlJ%0ou+3W(nS^xR4oew}xkk6>#Hr z-<~wb<;@lltjY2r6g&gX=_z(|mUeUgn#p1QD^_xt7BY%XD?7{f{>*mYQ|pbU>L4~6 z?-^(bUS*7UqPDqM9^~SSYW2iU!MU0rk_dq*n&eJ6MP7$UQN1T*^d<|6bTis*~?SG5cRc8B{iobcOU0q`Jp07;#r-H8>>2c~fYMYJWa?s{W_qOrNIjiDCBN#P1)=$$PJ>ux?FBgi2ZV2CsUHO; zXotr}=iOsuj@QC^hCuAqId^3h#G^#ai(dMiU)tsoh^Qg#INKOn?^;<j>mQSIg5M37j-PAq%a>fe8L3^ zA8gdr9RDtT>sR6OXQ4b1m+6u6|AV1VfH7EJ9)~b?J$dH_FJ?|T@9fMF+!hLM^L~TL zt!g^#AWJVSV$9YLg0H4XLX;&bbYT#i3jz#>5U|bx^@Y34`m_xcv>mMq+6CpSatU`J z)Q03co(y^GK5$#K0~EoDJ0gG`#Abp^+WA=M+Wzk!-0-&oQDCMC{>XFU^AIS-W}!0pSVBsWLkrXWxWAh6Eos;JcIXPFK)cT{Rc zk0r^6q=P6Rq3x(UtvX(kyH;o;-?kz`QMvPHxE%^|&e)VYWLh%FIp};Y<+B;J6>O$*>>tg3=h4o#r6?Z3np7DAi_ImCwrmp1S^0?@_t~U)g^r0PX3-_=1!*!1UDD8iLqyJsy-d~R(IxZ+PxD)- z5A;lb|Nh-h7%JHxg)ZZjz_uZpRrKko0{*OzPb18M$AoKKF*IfDJ3(C$l(MiiTE@2} z-~YB4Lshq)g2LJjKg1)k`dB5XdhZegA&snqlpwOlIC#@3GZ6PFAedRbr(&fw5kj~K zx!B=2c`3-5-_`*(VGULoozv(Lj|Umk=Sd3Ir+~F4o!VzPqCk-Ks-Kc6;T~Kqu-zMT zjbLTW{MOa`Tb-;xzHD=fQLvSU#`eQt7f~#I=m{;EW;sS8@`zD{Skr6=-IlkK%^trFnI6{aXvZ!>4~0K&^R(8`5Co(fH`A+AQ)VVPUANB>*8O@DNV{f;DJptzqyal! zBaVVC3;a|1MDai9I;U7sdWMZ|+qP{RXWO=I+qP}nwr$(Cb++}N_xj79v`O1ZnqG9K z7t?1gnu_$JEoCQf))VrR;Np~)=wbxX6oP!JWJ=N+X$^sn{aRs)e<%Q3Gt+9tnFOK} zP_2tU%Lbvz>aslJh@8a8R6L>acR>DPlQ$%f!qTPUcn(xLkO`X-Dpj@$71iPSBv+Vh zYd`*9EF}w-gdQ(qB!$J4=}Q1{uru(!u%(nS6bK^RrIScae57}Hn>v5Oni9!T_p8Ak zu9)_9Nhf4@jD+W3?7cOPLpIgk8%e+z9v2be^Tc~oTDI)e^dZ8*mkBI6^64NU$^&^wB`1$%BYEWO0G0uZ^9Tq#&NXB@b&5mBb0__ikS%wL#hA`~`GG#kx48|0 zKgdaANI@7+p3AN$0dMH-HoKdKHnDFIkrnnf;=V`-N;Sbtc7zX)f4?fbYXCfN2 zUn~I-b=G#JKvj)9lxRDmm>KPQ8^IG_z9fC*b&f6rPdDTyn@w>^@)(*m$o2Rw6*oqE z+InhQORE)ybYz=cI(Dy=jR{K?VN2%0bY>%C4@q*4Nzg#H1=VYRYlL!G@)!jM2D-fm%0>>%NOt83*TE+ka*$VKLiu6WVlrm6GqsltdWL*_t+{qvm2SeRzZf zGKxtY=wBprV!Ib?h2!yNog8oB$OE~P?UQTz%jun=&;$oCT`P_uG`-@GZGam4+v-Y2 zM@=_yi#H5-{p1)(j=$QNM~F{&K(V6RWnXhf@Hq=%y6+}>A92O2SFpE1Vm}1n7QU?& zoh?Z20KW-8Xvp4L=NxGYeT>e}{D_4#r1z15IET&)(;k|qCwXO>-Nr9gyGo0nlCsj_ ziKBO^;&%UXM#x&R;G4Bj9ds1r+sg_C$xZ9y_C3W-(EJHgFJ%Wh&kKMHAm|ZKl?Bz~ znt9z9-x}LRh=TQ%zi3sV+zp4nI1!eyZ(w;b_5~^3`da7{*)+~Kh#X99cJ6d=)n2qF zHTih@1X48R<;~6}wA<&>2PVwt+R&aS!2=sV=ZZ%_I465xxjK;EmN{}g2Quf-hQK?< z3!+0H_2JMurT=XRU&%oCMlR!+!8N7+O42@6h9{un!Rt$mcy~OIGpkNmm9C+pbb~L5 zJgSmD&emAzl(5>@!~h=9^7aF&3ura|!oTlBAwg_m>xtjv9%4#zgD(KKYa0t}6%bxs z5bL)}FivL?FQuWMEgNwayT1eWP9<-v}Vwvvr4i@_ufJy6T3 zWspdL%>{iGYHIQ#lxR!(Vl+MfDoA6Xquc}7e+WYZcK`xS9{slOD-K8jvJ%bVk)Cxw zf`{?(iH+V92Hh+R-8}0Nfe6057AoI$uFX?d=KdJ7@Xd!*b=IGOInpJ!HXlkD%RUUe zh$?UCjgB(GDk`QKS--Upsiv};(xRY$Pm_+0LA1kSh@y0uD_NJ7M%_`+jebdQb1;MG zhE3_0?-%tK&}4Oz%{f7 zo>6EQnh~}0+|jWxHjt7cmIek1atBnJO&KHwCWL4DA+7VTBwo+#Oejz}+dr??$c|%H zw_|Z1%gT)bq!$Lgn7t!J8uZYCI92)iQTaUeu^zPWK-I9l=$WtpvUReOho*b}5 z0IM!KhKxf%3oRi7ti)tLst#c8@XEk9q{dbi^`$Nb=gXzz1)nYfNIexuapDS5c7}tE zG$Pl%I5{>l3xnlDn%Uef=1surH^xmE&SQDJ zS>-pf;|-E-%^xHbuY~k0AYYRtEY$PA5A=bs6YO*z{zJf*Cq@iPbF7vt0GW9%LP46x z%lY!X3ecPE++Zy!axqzdjJ?)_mLF8FE% z0Z=Kmht=%17xSnOKM&&a0sp18&gKc*QRck!HJa%>jx7_vlGDB@I0c`1duw^xP^;P5F!9y&%dFdtdBx5wER8Iu&C=RpV$hdfSs zEaJi#Z?%Q>k?=%AP?UM2-!;*YoMKiSA{%&suL+dU#iOY^6392HhC1!%TnMGROkxxl zwJ6{be%knI0d~SRFbSlWcOKttVFV{(ggBV@XqnMxojvd?n{YJDUK7>nCK|eQgLOK` zrv|l;z&38?ioH@Nrm~)QCv*VkxW)JGPjK?*?q86?jkIgbp>|Ic*K+WozN*>t+|wV} z%brHSeQ(&?PnRkB0=tfTbNxamu9WNWcU@TMv?wWZP5jdtKpX=2vD9dMEVB%8wW*V^ z*r-PE_j%{{-TzcqqIl^F8-62DQ;qC-n7|l;hMOcGl4>ntVE4-zUh*Rk+!pjIw z@mCP4`eGqjE8sOc~ExJpvc?e^MLeNzB%fYK;FK7xtw8YHI0qL%mLWFmrZ!*@iz zv1(;Z;4Zq5=VpmWm6U-R<{sXE0o}q3*Vvo`?a9Iq$cuG&gdv_BVPjEX5k9;OkDy6G{o%>%LymQJUIj4CyWm;O61Bs zsfIEn*Ox?Cah85ZVc3G6P!@@q5*)EjpPOL<2Sjf%8qNRklMF3d$Raw$8pfiUnN*X^ zXvS$gkx-wQK7%x(iKhxQ1|H)h-bXoQIn4F<0wa6YKyf*^3BJYq(1^l?K%@p)M1hFy zisU`bk6m|(tL9~`NXb0IfHcuvaIWgTO+=9rLaDocmT+|F zw1*-1OI{cEZ!JXFB9+7%bEX{FK&Azd84)DiOh#{^14l0w`~ka&GH8R0K53$dneq`; zX1vlJFJ!wrEgG*S{N&R<{FL(#9=$`g4+8xJ@uq82N<_>_{L3}sXoYEel`Oy>6`96% z^!J}GTQ`uE{pj6}+i+Q}9xNj!Ju#e+-I{t9zcC-?HehbS){TJH3P^b<)NH=`ArlyqkYYz%FUVmH;y*lLPCu5r$ z&okn-ZbV1V;d2Q<<5c5xYA?#4Lk-owFosd%+09Uc(S<5To^z;pbJ&?v$({GlpI^iu z-}~ROuO8C=y&}M$-IFJ^!+YDbu5tB0Vx+L4!Sn+8V){p@(XeUkbYTHGpA0#H2M4e7{JW+l<);bTw6Yw6Wk*uY{@u607qp745HZ$M+FZuBv(9cN&jFFsARb7cr@i>??>x!jU?$)D2+4N>*ZN)ds)=I!_9#Q=t6+E=A=d1QANXNT z%Z4$va~TECvoXusN;E>9DX3ePF)PIeL(UgIGFq2+NK}-~HZ-i{fp1BtUIVOSA?JGr zYR^|;=K+L-(ZcCQ8aX@LNFAIaS$#bc^1 zO<4z<8JYoUNut)MoM-eow&YE}?81B1sPF73bwGhcSO2Y(x?iDvL#t2}$G%P8?!0^t ziHt#0&Fpz{Z~w!wR#@-11A6Xjaers`-KD$!IoFnryP|{5EAo4c_)n%)lUn0H!aKME zjOL(pzdo~68d|FK_Kv2#eIMwWtS>ImHRvPq@Fz*$gKT;A+32<}az*wM;sOG?tl%l; znt%A^TU!MMqQ>AB)?JBH;?#IHNr7gXO#fW!B|vZ`<(c40XQ^eys>@0=v$FPx1N`}{ zzQfEz()~4UZ3BI<*&x+r>>xziTreck33JoqJ)k}Cqz_;iU`~kAvPGygPRXAE{rE$< zA7;28>*2jr<=9_rS*K~khH;0NzJeohnXFR2lKmNQP4aAyMlruk4M#n|6Gw(Q?`y&*^p--Xbpv_34^ zQ?7tpsEQPBIvbn|0L6<<7;J0P6* zwnv#xi~ved`V(sglSI3h8861l_Tqbvy)&T(X4JX%C;Nm8#<(<^_=~Rd58dYoXnkG2 zgj50WQ~OXpwr{K9-_FubWXGyk*}h0&yMg!5flHL&KWe%}T2CvmjV^L7RZAeoa!H_J z{~_&UHtO6im!@<-pkQ`jl&eWG=^fX&LVJ3V9=^Fe ze@1XN{$v`CxnC2Q8je;(Jf!kaGq($}P6at6d}mn3=C^p9@_U+D`U}BOy7`L#?g(i@ z&3hu`j!k^9HWqa}mCsI*aIo)jV5LEx=xeavb8xMJ7#-3eBq{+T-#Ej7IWnjPfEoBu z#FKx0xOS|tp4D@ux}#(R#)TJ4hW8uvPsR_lFcWfo%?_?71|PZ--N#LfDO(l;p-w z5_JIN(4xgm{JmF)3blj`mD#;YW0?z;(PbP{wCJ`AVE8^`bcEA@l%UX|?l{Hyn={V1 z$IdVCbWT6ThJqypU zG>p&IR%4qlPnanW?);hsYym=E15-5BqFwV zVJFM@Ym)WDZ4@{$^WRBIrs5<$8U*-EGESAj)-qAKs-P;sB=bj*`WK!jQ$JS20xxO1 zMKt>OvXXuVZ_fU~h`S&T{yd&+`~?``YIuB;Pq8rCy_llOP=xbEC!uR7A(j%!O$>
    06?;u0I*e(lQa!t+}aLIt)=trbpLrkOR= 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg.meta new file mode 100644 index 00000000000..f17c9863bed --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3b6419b3ddd8e3c59a084fbccd38354b +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT new file mode 100644 index 00000000000..207a2a734ad --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT @@ -0,0 +1,309 @@ +.NET Core uses third-party libraries or other resources that may be +distributed under licenses different than the .NET Core software. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Post an issue or email us: + + dotnet@microsoft.com + +The attached notices are provided for information only. + +License notice for Slicing-by-8 +------------------------------- + +http://sourceforge.net/projects/slicing-by-8/ + +Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved + + +This software program is licensed subject to the BSD License, available at +http://www.opensource.org/licenses/bsd-license.html. + + +License notice for Unicode data +------------------------------- + +http://www.unicode.org/copyright.html#License + +Copyright © 1991-2017 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. + +License notice for Zlib +----------------------- + +https://github.com/madler/zlib +http://zlib.net/zlib_license.html + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +*/ + +License notice for Mono +------------------------------- + +http://www.mono-project.com/docs/about-mono/ + +Copyright (c) .NET Foundation Contributors + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the Software), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License notice for International Organization for Standardization +----------------------------------------------------------------- + +Portions (C) International Organization for Standardization 1986: + Permission to copy in any form is granted for use with + conforming SGML systems and applications as defined in + ISO 8879, provided this notice is included in all copies. + +License notice for Intel +------------------------ + +"Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License notice for Xamarin and Novell +------------------------------------- + +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Copyright (c) 2011 Novell, Inc (http://www.novell.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Third party notice for W3C +-------------------------- + +"W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE +Status: This license takes effect 13 May, 2015. +This work is being provided by the copyright holders under the following license. +License +By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions. +Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the work or portions thereof, including modifications: +The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. +Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software and Document Short Notice should be included. +Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived from [title and URI of the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)." +Disclaimers +THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT. +The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission. Title to copyright in this work will at all times remain with copyright holders." + +License notice for Bit Twiddling Hacks +-------------------------------------- + +Bit Twiddling Hacks + +By Sean Eron Anderson +seander@cs.stanford.edu + +Individually, the code snippets here are in the public domain (unless otherwise +noted) — feel free to use them however you please. The aggregate collection and +descriptions are © 1997-2005 Sean Eron Anderson. The code and descriptions are +distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY and +without even the implied warranty of merchantability or fitness for a particular +purpose. + +License notice for Brotli +-------------------------------------- + +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +compress_fragment.c: +Copyright (c) 2011, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +decode_fuzzer.c: +Copyright (c) 2015 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT.meta new file mode 100644 index 00000000000..6e0890522ad --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b3fe6450b2adebdadb6f022c600c54ae +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib.meta new file mode 100644 index 00000000000..e9b452b3e60 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: db995c57b21d2a886862da3e375894a2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0.meta new file mode 100644 index 00000000000..fd6c8e2d6ab --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f9f81377355dade297ceb76b84bab10 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll new file mode 100644 index 0000000000000000000000000000000000000000..bdfc501e9647719549793297acb072d33067d4e5 GIT binary patch literal 148760 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 IXGb{$00BiQzyJUM literal 0 HcmV?d00001 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll.meta new file mode 100644 index 00000000000..7e3cbb61986 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 30a29d5b265da523ca20d43a264e7877 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml new file mode 100644 index 00000000000..de9af8989be --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml @@ -0,0 +1,355 @@ + + + System.Memory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml.meta new file mode 100644 index 00000000000..aecf5eac9f7 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3a1527b0a64676fe88542f420811e1c6 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt.meta new file mode 100644 index 00000000000..f52950d847e --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 245d848d2e32c738eaabe264d570fa28 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt new file mode 100644 index 00000000000..84098337995 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt @@ -0,0 +1 @@ +c6cf790234e063b855fcdb50f3fb1b3cfac73275 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt.meta new file mode 100644 index 00000000000..805c58fd0ca --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f8033dc14c362de7abb5c1d4ba82377b +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2.meta new file mode 100644 index 00000000000..597fb58dfa1 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 28121a23158a08fd099fee07651b6fe5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT new file mode 100644 index 00000000000..fa3121dfaf7 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT.meta new file mode 100644 index 00000000000..3e33a2ffd85 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a9abbe1e2cf90e99cb3200e0e16d127b +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..4f464e12ed6889d99bc849a269dd8a3f547a81f5 GIT binary patch literal 104723 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

    dKP05&Bo2xtTrg9PEq4=FVF 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg.meta new file mode 100644 index 00000000000..e670a731ae0 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a0592ab03350126988dc73996196f102 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT new file mode 100644 index 00000000000..207a2a734ad --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT @@ -0,0 +1,309 @@ +.NET Core uses third-party libraries or other resources that may be +distributed under licenses different than the .NET Core software. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Post an issue or email us: + + dotnet@microsoft.com + +The attached notices are provided for information only. + +License notice for Slicing-by-8 +------------------------------- + +http://sourceforge.net/projects/slicing-by-8/ + +Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved + + +This software program is licensed subject to the BSD License, available at +http://www.opensource.org/licenses/bsd-license.html. + + +License notice for Unicode data +------------------------------- + +http://www.unicode.org/copyright.html#License + +Copyright © 1991-2017 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. + +License notice for Zlib +----------------------- + +https://github.com/madler/zlib +http://zlib.net/zlib_license.html + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +*/ + +License notice for Mono +------------------------------- + +http://www.mono-project.com/docs/about-mono/ + +Copyright (c) .NET Foundation Contributors + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the Software), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License notice for International Organization for Standardization +----------------------------------------------------------------- + +Portions (C) International Organization for Standardization 1986: + Permission to copy in any form is granted for use with + conforming SGML systems and applications as defined in + ISO 8879, provided this notice is included in all copies. + +License notice for Intel +------------------------ + +"Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License notice for Xamarin and Novell +------------------------------------- + +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Copyright (c) 2011 Novell, Inc (http://www.novell.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Third party notice for W3C +-------------------------- + +"W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE +Status: This license takes effect 13 May, 2015. +This work is being provided by the copyright holders under the following license. +License +By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions. +Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the work or portions thereof, including modifications: +The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. +Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software and Document Short Notice should be included. +Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived from [title and URI of the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)." +Disclaimers +THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT. +The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission. Title to copyright in this work will at all times remain with copyright holders." + +License notice for Bit Twiddling Hacks +-------------------------------------- + +Bit Twiddling Hacks + +By Sean Eron Anderson +seander@cs.stanford.edu + +Individually, the code snippets here are in the public domain (unless otherwise +noted) — feel free to use them however you please. The aggregate collection and +descriptions are © 1997-2005 Sean Eron Anderson. The code and descriptions are +distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY and +without even the implied warranty of merchantability or fitness for a particular +purpose. + +License notice for Brotli +-------------------------------------- + +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +compress_fragment.c: +Copyright (c) 2011, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +decode_fuzzer.c: +Copyright (c) 2015 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT.meta new file mode 100644 index 00000000000..23ab378274a --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ad2aa0f35903c91a3a6f4e68038686d5 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib.meta new file mode 100644 index 00000000000..5ce5490008e --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b36206566e8c87fb0a48d58bcbeeac35 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0.meta new file mode 100644 index 00000000000..03338124f98 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00b4ff731ea89be429d779a12bfcc2e1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll new file mode 100644 index 0000000000000000000000000000000000000000..3156239266db9cceede249731f00c3822e479a1f GIT binary patch literal 23600 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 OyIXQg_#$)@0sTLk9O=pc literal 0 HcmV?d00001 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll.meta new file mode 100644 index 00000000000..b1136d6d6bc --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c302643d7365a215dacc6f0fe5cdfd88 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml new file mode 100644 index 00000000000..84c02132f37 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml @@ -0,0 +1,200 @@ + + + System.Runtime.CompilerServices.Unsafe + + + +

    Contains generic, low-level functionality for manipulating pointers. + + + Adds an element offset to the given reference. + The reference to add the offset to. + The offset to add. + The type of reference. + A new reference that reflects the addition of offset to pointer. + + + Adds an element offset to the given reference. + The reference to add the offset to. + The offset to add. + The type of reference. + A new reference that reflects the addition of offset to pointer. + + + Adds a byte offset to the given reference. + The reference to add the offset to. + The offset to add. + The type of reference. + A new reference that reflects the addition of byte offset to pointer. + + + Determines whether the specified references point to the same location. + The first reference to compare. + The second reference to compare. + The type of reference. + true if left and right point to the same location; otherwise, false. + + + Casts the given object to the specified type. + The object to cast. + The type which the object will be cast to. + The original object, casted to the given type. + + + Reinterprets the given reference as a reference to a value of type TTo. + The reference to reinterpret. + The type of reference to reinterpret.. + The desired type of the reference. + A reference to a value of type TTo. + + + Returns a pointer to the given by-ref parameter. + The object whose pointer is obtained. + The type of object. + A pointer to the given value. + + + Reinterprets the given location as a reference to a value of type T. + The location of the value to reference. + The type of the interpreted location. + A reference to a value of type T. + + + Determines the byte offset from origin to target from the given references. + The reference to origin. + The reference to target. + The type of reference. + Byte offset from origin to target i.e. target - origin. + + + Copies a value of type T to the given location. + The location to copy to. + A reference to the value to copy. + The type of value to copy. + + + Copies a value of type T to the given location. + The location to copy to. + A pointer to the value to copy. + The type of value to copy. + + + Copies bytes from the source address to the destination address. + The destination address to copy to. + The source address to copy from. + The number of bytes to copy. + + + Copies bytes from the source address to the destination address. + The destination address to copy to. + The source address to copy from. + The number of bytes to copy. + + + Copies bytes from the source address to the destination address +without assuming architecture dependent alignment of the addresses. + The destination address to copy to. + The source address to copy from. + The number of bytes to copy. + + + Copies bytes from the source address to the destination address +without assuming architecture dependent alignment of the addresses. + The destination address to copy to. + The source address to copy from. + The number of bytes to copy. + + + Initializes a block of memory at the given location with a given initial value. + The address of the start of the memory block to initialize. + The value to initialize the block to. + The number of bytes to initialize. + + + Initializes a block of memory at the given location with a given initial value. + The address of the start of the memory block to initialize. + The value to initialize the block to. + The number of bytes to initialize. + + + Initializes a block of memory at the given location with a given initial value +without assuming architecture dependent alignment of the address. + The address of the start of the memory block to initialize. + The value to initialize the block to. + The number of bytes to initialize. + + + Initializes a block of memory at the given location with a given initial value +without assuming architecture dependent alignment of the address. + The address of the start of the memory block to initialize. + The value to initialize the block to. + The number of bytes to initialize. + + + Reads a value of type T from the given location. + The location to read from. + The type to read. + An object of type T read from the given location. + + + Reads a value of type T from the given location +without assuming architecture dependent alignment of the addresses. + The location to read from. + The type to read. + An object of type T read from the given location. + + + Reads a value of type T from the given location +without assuming architecture dependent alignment of the addresses. + The location to read from. + The type to read. + An object of type T read from the given location. + + + Returns the size of an object of the given type parameter. + The type of object whose size is retrieved. + The size of an object of type T. + + + Subtracts an element offset from the given reference. + The reference to subtract the offset from. + The offset to subtract. + The type of reference. + A new reference that reflects the subraction of offset from pointer. + + + Subtracts an element offset from the given reference. + The reference to subtract the offset from. + The offset to subtract. + The type of reference. + A new reference that reflects the subraction of offset from pointer. + + + Subtracts a byte offset from the given reference. + The reference to subtract the offset from. + + The type of reference. + A new reference that reflects the subraction of byte offset from pointer. + + + Writes a value of type T to the given location. + The location to write to. + The value to write. + The type of value to write. + + + Writes a value of type T to the given location +without assuming architecture dependent alignment of the addresses. + The location to write to. + The value to write. + The type of value to write. + + + Writes a value of type T to the given location +without assuming architecture dependent alignment of the addresses. + The location to write to. + The value to write. + The type of value to write. + + + \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml.meta new file mode 100644 index 00000000000..c4a83ad00a4 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9ba4a7a6f2232e96a98073f2e8c1c795 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt.meta new file mode 100644 index 00000000000..11818647baf --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 53d0e173bdb86477ebe32b6d0f5e588c +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt new file mode 100644 index 00000000000..7558087f901 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt @@ -0,0 +1 @@ +02b11eeee1fbc5f3ef43a1452fe07efd25fa1715 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt.meta new file mode 100644 index 00000000000..8b9257927a0 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 07e253f0e146e6c43a6ec6b0b58212ce +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts.meta new file mode 100644 index 00000000000..8b5f71efd3d --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10dd1ca43de00b578b7a58913a7330cf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs new file mode 100644 index 00000000000..e6604e9109a --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs @@ -0,0 +1,1709 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: client_api.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace ClientApi { + + /// Holder for reflection information generated from client_api.proto + public static partial class ClientApiReflection { + + #region Descriptor + /// File descriptor for client_api.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ClientApiReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChBjbGllbnRfYXBpLnByb3RvEgpjbGllbnRfYXBpIpUCCgdNZXNzYWdlEjAK", + "DGZ1bmN0aW9uQ2FsbBgBIAEoCzIYLmNsaWVudF9hcGkuRnVuY3Rpb25DYWxs", + "SAASPAoSc3Vic2NyaXB0aW9uVXBkYXRlGAIgASgLMh4uY2xpZW50X2FwaS5T", + "dWJzY3JpcHRpb25VcGRhdGVIABIiCgVldmVudBgDIAEoCzIRLmNsaWVudF9h", + "cGkuRXZlbnRIABI6ChF0cmFuc2FjdGlvblVwZGF0ZRgEIAEoCzIdLmNsaWVu", + "dF9hcGkuVHJhbnNhY3Rpb25VcGRhdGVIABIyCg1pZGVudGl0eVRva2VuGAUg", + "ASgLMhkuY2xpZW50X2FwaS5JZGVudGl0eVRva2VuSABCBgoEdHlwZSIwCg1J", + "ZGVudGl0eVRva2VuEhAKCGlkZW50aXR5GAEgASgMEg0KBXRva2VuGAIgASgJ", + "IjEKDEZ1bmN0aW9uQ2FsbBIPCgdyZWR1Y2VyGAEgASgJEhAKCGFyZ0J5dGVz", + "GAIgASgMIpkCCgVFdmVudBIRCgl0aW1lc3RhbXAYASABKAQSFgoOY2FsbGVy", + "SWRlbnRpdHkYAiABKAwSLgoMZnVuY3Rpb25DYWxsGAMgASgLMhguY2xpZW50", + "X2FwaS5GdW5jdGlvbkNhbGwSKAoGc3RhdHVzGAQgASgOMhguY2xpZW50X2Fw", + "aS5FdmVudC5TdGF0dXMSDwoHbWVzc2FnZRgFIAEoCRIaChJlbmVyZ3lfcXVh", + "bnRhX3VzZWQYBiABKAMSJgoeaG9zdF9leGVjdXRpb25fZHVyYXRpb25fbWlj", + "cm9zGAcgASgEIjYKBlN0YXR1cxINCgljb21taXR0ZWQQABIKCgZmYWlsZWQQ", + "ARIRCg1vdXRfb2ZfZW5lcmd5EAIiQwoSU3Vic2NyaXB0aW9uVXBkYXRlEi0K", + "DHRhYmxlVXBkYXRlcxgBIAMoCzIXLmNsaWVudF9hcGkuVGFibGVVcGRhdGUi", + "bAoLVGFibGVVcGRhdGUSDwoHdGFibGVJZBgBIAEoDRIRCgl0YWJsZU5hbWUY", + "AiABKAkSOQoSdGFibGVSb3dPcGVyYXRpb25zGAMgAygLMh0uY2xpZW50X2Fw", + "aS5UYWJsZVJvd09wZXJhdGlvbiKSAQoRVGFibGVSb3dPcGVyYXRpb24SNwoC", + "b3AYASABKA4yKy5jbGllbnRfYXBpLlRhYmxlUm93T3BlcmF0aW9uLk9wZXJh", + "dGlvblR5cGUSDgoGcm93X3BrGAIgASgMEgsKA3JvdxgDIAEoDCInCg1PcGVy", + "YXRpb25UeXBlEgoKBkRFTEVURRAAEgoKBklOU0VSVBABInEKEVRyYW5zYWN0", + "aW9uVXBkYXRlEiAKBWV2ZW50GAEgASgLMhEuY2xpZW50X2FwaS5FdmVudBI6", + "ChJzdWJzY3JpcHRpb25VcGRhdGUYAiABKAsyHi5jbGllbnRfYXBpLlN1YnNj", + "cmlwdGlvblVwZGF0ZWIGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Message), global::ClientApi.Message.Parser, new[]{ "FunctionCall", "SubscriptionUpdate", "Event", "TransactionUpdate", "IdentityToken" }, new[]{ "Type" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.IdentityToken), global::ClientApi.IdentityToken.Parser, new[]{ "Identity", "Token" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.FunctionCall), global::ClientApi.FunctionCall.Parser, new[]{ "Reducer", "ArgBytes" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Event), global::ClientApi.Event.Parser, new[]{ "Timestamp", "CallerIdentity", "FunctionCall", "Status", "Message", "EnergyQuantaUsed", "HostExecutionDurationMicros" }, null, new[]{ typeof(global::ClientApi.Event.Types.Status) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.SubscriptionUpdate), global::ClientApi.SubscriptionUpdate.Parser, new[]{ "TableUpdates" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableUpdate), global::ClientApi.TableUpdate.Parser, new[]{ "TableId", "TableName", "TableRowOperations" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableRowOperation), global::ClientApi.TableRowOperation.Parser, new[]{ "Op", "RowPk", "Row" }, null, new[]{ typeof(global::ClientApi.TableRowOperation.Types.OperationType) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TransactionUpdate), global::ClientApi.TransactionUpdate.Parser, new[]{ "Event", "SubscriptionUpdate" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /////// Generic Message ////// + /// TODO: Theoretically this format could be replaced by TypeValue/TypeDef + /// but I don't think we want to do that yet. + /// TODO: Split this up into ServerBound and ClientBound if there's no overlap + /// + public sealed partial class Message : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Message()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Message(Message other) : this() { + switch (other.TypeCase) { + case TypeOneofCase.FunctionCall: + FunctionCall = other.FunctionCall.Clone(); + break; + case TypeOneofCase.SubscriptionUpdate: + SubscriptionUpdate = other.SubscriptionUpdate.Clone(); + break; + case TypeOneofCase.Event: + Event = other.Event.Clone(); + break; + case TypeOneofCase.TransactionUpdate: + TransactionUpdate = other.TransactionUpdate.Clone(); + break; + case TypeOneofCase.IdentityToken: + IdentityToken = other.IdentityToken.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Message Clone() { + return new Message(this); + } + + /// Field number for the "functionCall" field. + public const int FunctionCallFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.FunctionCall FunctionCall { + get { return typeCase_ == TypeOneofCase.FunctionCall ? (global::ClientApi.FunctionCall) type_ : null; } + set { + type_ = value; + typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.FunctionCall; + } + } + + /// Field number for the "subscriptionUpdate" field. + public const int SubscriptionUpdateFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.SubscriptionUpdate SubscriptionUpdate { + get { return typeCase_ == TypeOneofCase.SubscriptionUpdate ? (global::ClientApi.SubscriptionUpdate) type_ : null; } + set { + type_ = value; + typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.SubscriptionUpdate; + } + } + + /// Field number for the "event" field. + public const int EventFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.Event Event { + get { return typeCase_ == TypeOneofCase.Event ? (global::ClientApi.Event) type_ : null; } + set { + type_ = value; + typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.Event; + } + } + + /// Field number for the "transactionUpdate" field. + public const int TransactionUpdateFieldNumber = 4; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.TransactionUpdate TransactionUpdate { + get { return typeCase_ == TypeOneofCase.TransactionUpdate ? (global::ClientApi.TransactionUpdate) type_ : null; } + set { + type_ = value; + typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.TransactionUpdate; + } + } + + /// Field number for the "identityToken" field. + public const int IdentityTokenFieldNumber = 5; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.IdentityToken IdentityToken { + get { return typeCase_ == TypeOneofCase.IdentityToken ? (global::ClientApi.IdentityToken) type_ : null; } + set { + type_ = value; + typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.IdentityToken; + } + } + + private object type_; + /// Enum of possible cases for the "type" oneof. + public enum TypeOneofCase { + None = 0, + FunctionCall = 1, + SubscriptionUpdate = 2, + Event = 3, + TransactionUpdate = 4, + IdentityToken = 5, + } + private TypeOneofCase typeCase_ = TypeOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TypeOneofCase TypeCase { + get { return typeCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearType() { + typeCase_ = TypeOneofCase.None; + type_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(FunctionCall, other.FunctionCall)) return false; + if (!object.Equals(SubscriptionUpdate, other.SubscriptionUpdate)) return false; + if (!object.Equals(Event, other.Event)) return false; + if (!object.Equals(TransactionUpdate, other.TransactionUpdate)) return false; + if (!object.Equals(IdentityToken, other.IdentityToken)) return false; + if (TypeCase != other.TypeCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (typeCase_ == TypeOneofCase.FunctionCall) hash ^= FunctionCall.GetHashCode(); + if (typeCase_ == TypeOneofCase.SubscriptionUpdate) hash ^= SubscriptionUpdate.GetHashCode(); + if (typeCase_ == TypeOneofCase.Event) hash ^= Event.GetHashCode(); + if (typeCase_ == TypeOneofCase.TransactionUpdate) hash ^= TransactionUpdate.GetHashCode(); + if (typeCase_ == TypeOneofCase.IdentityToken) hash ^= IdentityToken.GetHashCode(); + hash ^= (int) typeCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (typeCase_ == TypeOneofCase.FunctionCall) { + output.WriteRawTag(10); + output.WriteMessage(FunctionCall); + } + if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { + output.WriteRawTag(18); + output.WriteMessage(SubscriptionUpdate); + } + if (typeCase_ == TypeOneofCase.Event) { + output.WriteRawTag(26); + output.WriteMessage(Event); + } + if (typeCase_ == TypeOneofCase.TransactionUpdate) { + output.WriteRawTag(34); + output.WriteMessage(TransactionUpdate); + } + if (typeCase_ == TypeOneofCase.IdentityToken) { + output.WriteRawTag(42); + output.WriteMessage(IdentityToken); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (typeCase_ == TypeOneofCase.FunctionCall) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FunctionCall); + } + if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubscriptionUpdate); + } + if (typeCase_ == TypeOneofCase.Event) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Event); + } + if (typeCase_ == TypeOneofCase.TransactionUpdate) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(TransactionUpdate); + } + if (typeCase_ == TypeOneofCase.IdentityToken) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(IdentityToken); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Message other) { + if (other == null) { + return; + } + switch (other.TypeCase) { + case TypeOneofCase.FunctionCall: + if (FunctionCall == null) { + FunctionCall = new global::ClientApi.FunctionCall(); + } + FunctionCall.MergeFrom(other.FunctionCall); + break; + case TypeOneofCase.SubscriptionUpdate: + if (SubscriptionUpdate == null) { + SubscriptionUpdate = new global::ClientApi.SubscriptionUpdate(); + } + SubscriptionUpdate.MergeFrom(other.SubscriptionUpdate); + break; + case TypeOneofCase.Event: + if (Event == null) { + Event = new global::ClientApi.Event(); + } + Event.MergeFrom(other.Event); + break; + case TypeOneofCase.TransactionUpdate: + if (TransactionUpdate == null) { + TransactionUpdate = new global::ClientApi.TransactionUpdate(); + } + TransactionUpdate.MergeFrom(other.TransactionUpdate); + break; + case TypeOneofCase.IdentityToken: + if (IdentityToken == null) { + IdentityToken = new global::ClientApi.IdentityToken(); + } + IdentityToken.MergeFrom(other.IdentityToken); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::ClientApi.FunctionCall subBuilder = new global::ClientApi.FunctionCall(); + if (typeCase_ == TypeOneofCase.FunctionCall) { + subBuilder.MergeFrom(FunctionCall); + } + input.ReadMessage(subBuilder); + FunctionCall = subBuilder; + break; + } + case 18: { + global::ClientApi.SubscriptionUpdate subBuilder = new global::ClientApi.SubscriptionUpdate(); + if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { + subBuilder.MergeFrom(SubscriptionUpdate); + } + input.ReadMessage(subBuilder); + SubscriptionUpdate = subBuilder; + break; + } + case 26: { + global::ClientApi.Event subBuilder = new global::ClientApi.Event(); + if (typeCase_ == TypeOneofCase.Event) { + subBuilder.MergeFrom(Event); + } + input.ReadMessage(subBuilder); + Event = subBuilder; + break; + } + case 34: { + global::ClientApi.TransactionUpdate subBuilder = new global::ClientApi.TransactionUpdate(); + if (typeCase_ == TypeOneofCase.TransactionUpdate) { + subBuilder.MergeFrom(TransactionUpdate); + } + input.ReadMessage(subBuilder); + TransactionUpdate = subBuilder; + break; + } + case 42: { + global::ClientApi.IdentityToken subBuilder = new global::ClientApi.IdentityToken(); + if (typeCase_ == TypeOneofCase.IdentityToken) { + subBuilder.MergeFrom(IdentityToken); + } + input.ReadMessage(subBuilder); + IdentityToken = subBuilder; + break; + } + } + } + } + + } + + public sealed partial class IdentityToken : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new IdentityToken()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public IdentityToken() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public IdentityToken(IdentityToken other) : this() { + identity_ = other.identity_; + token_ = other.token_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public IdentityToken Clone() { + return new IdentityToken(this); + } + + /// Field number for the "identity" field. + public const int IdentityFieldNumber = 1; + private pb::ByteString identity_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Identity { + get { return identity_; } + set { + identity_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "token" field. + public const int TokenFieldNumber = 2; + private string token_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Token { + get { return token_; } + set { + token_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as IdentityToken); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(IdentityToken other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Identity != other.Identity) return false; + if (Token != other.Token) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Identity.Length != 0) hash ^= Identity.GetHashCode(); + if (Token.Length != 0) hash ^= Token.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Identity.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Identity); + } + if (Token.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Token); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Identity.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Identity); + } + if (Token.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Token); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(IdentityToken other) { + if (other == null) { + return; + } + if (other.Identity.Length != 0) { + Identity = other.Identity; + } + if (other.Token.Length != 0) { + Token = other.Token; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Identity = input.ReadBytes(); + break; + } + case 18: { + Token = input.ReadString(); + break; + } + } + } + } + + } + + /// + /// TODO: Evaluate if it makes sense for this to also include the + /// identity and name of the module this is calling + /// + public sealed partial class FunctionCall : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FunctionCall()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FunctionCall() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FunctionCall(FunctionCall other) : this() { + reducer_ = other.reducer_; + argBytes_ = other.argBytes_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FunctionCall Clone() { + return new FunctionCall(this); + } + + /// Field number for the "reducer" field. + public const int ReducerFieldNumber = 1; + private string reducer_ = ""; + /// + /// TODO: Maybe this should be replaced with an int identifier for performance? + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Reducer { + get { return reducer_; } + set { + reducer_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "argBytes" field. + public const int ArgBytesFieldNumber = 2; + private pb::ByteString argBytes_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString ArgBytes { + get { return argBytes_; } + set { + argBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FunctionCall); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FunctionCall other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Reducer != other.Reducer) return false; + if (ArgBytes != other.ArgBytes) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Reducer.Length != 0) hash ^= Reducer.GetHashCode(); + if (ArgBytes.Length != 0) hash ^= ArgBytes.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Reducer.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Reducer); + } + if (ArgBytes.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(ArgBytes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Reducer.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Reducer); + } + if (ArgBytes.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(ArgBytes); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FunctionCall other) { + if (other == null) { + return; + } + if (other.Reducer.Length != 0) { + Reducer = other.Reducer; + } + if (other.ArgBytes.Length != 0) { + ArgBytes = other.ArgBytes; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Reducer = input.ReadString(); + break; + } + case 18: { + ArgBytes = input.ReadBytes(); + break; + } + } + } + } + + } + + public sealed partial class Event : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Event()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Event() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Event(Event other) : this() { + timestamp_ = other.timestamp_; + callerIdentity_ = other.callerIdentity_; + functionCall_ = other.functionCall_ != null ? other.functionCall_.Clone() : null; + status_ = other.status_; + message_ = other.message_; + energyQuantaUsed_ = other.energyQuantaUsed_; + hostExecutionDurationMicros_ = other.hostExecutionDurationMicros_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Event Clone() { + return new Event(this); + } + + /// Field number for the "timestamp" field. + public const int TimestampFieldNumber = 1; + private ulong timestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong Timestamp { + get { return timestamp_; } + set { + timestamp_ = value; + } + } + + /// Field number for the "callerIdentity" field. + public const int CallerIdentityFieldNumber = 2; + private pb::ByteString callerIdentity_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString CallerIdentity { + get { return callerIdentity_; } + set { + callerIdentity_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "functionCall" field. + public const int FunctionCallFieldNumber = 3; + private global::ClientApi.FunctionCall functionCall_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.FunctionCall FunctionCall { + get { return functionCall_; } + set { + functionCall_ = value; + } + } + + /// Field number for the "status" field. + public const int StatusFieldNumber = 4; + private global::ClientApi.Event.Types.Status status_ = global::ClientApi.Event.Types.Status.Committed; + /// + /// TODO: arguably these should go inside an EventStatus message + /// since success doesn't have a message + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.Event.Types.Status Status { + get { return status_; } + set { + status_ = value; + } + } + + /// Field number for the "message" field. + public const int MessageFieldNumber = 5; + private string message_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Message { + get { return message_; } + set { + message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "energy_quanta_used" field. + public const int EnergyQuantaUsedFieldNumber = 6; + private long energyQuantaUsed_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long EnergyQuantaUsed { + get { return energyQuantaUsed_; } + set { + energyQuantaUsed_ = value; + } + } + + /// Field number for the "host_execution_duration_micros" field. + public const int HostExecutionDurationMicrosFieldNumber = 7; + private ulong hostExecutionDurationMicros_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong HostExecutionDurationMicros { + get { return hostExecutionDurationMicros_; } + set { + hostExecutionDurationMicros_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Event); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Event other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Timestamp != other.Timestamp) return false; + if (CallerIdentity != other.CallerIdentity) return false; + if (!object.Equals(FunctionCall, other.FunctionCall)) return false; + if (Status != other.Status) return false; + if (Message != other.Message) return false; + if (EnergyQuantaUsed != other.EnergyQuantaUsed) return false; + if (HostExecutionDurationMicros != other.HostExecutionDurationMicros) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Timestamp != 0UL) hash ^= Timestamp.GetHashCode(); + if (CallerIdentity.Length != 0) hash ^= CallerIdentity.GetHashCode(); + if (functionCall_ != null) hash ^= FunctionCall.GetHashCode(); + if (Status != global::ClientApi.Event.Types.Status.Committed) hash ^= Status.GetHashCode(); + if (Message.Length != 0) hash ^= Message.GetHashCode(); + if (EnergyQuantaUsed != 0L) hash ^= EnergyQuantaUsed.GetHashCode(); + if (HostExecutionDurationMicros != 0UL) hash ^= HostExecutionDurationMicros.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Timestamp != 0UL) { + output.WriteRawTag(8); + output.WriteUInt64(Timestamp); + } + if (CallerIdentity.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(CallerIdentity); + } + if (functionCall_ != null) { + output.WriteRawTag(26); + output.WriteMessage(FunctionCall); + } + if (Status != global::ClientApi.Event.Types.Status.Committed) { + output.WriteRawTag(32); + output.WriteEnum((int) Status); + } + if (Message.Length != 0) { + output.WriteRawTag(42); + output.WriteString(Message); + } + if (EnergyQuantaUsed != 0L) { + output.WriteRawTag(48); + output.WriteInt64(EnergyQuantaUsed); + } + if (HostExecutionDurationMicros != 0UL) { + output.WriteRawTag(56); + output.WriteUInt64(HostExecutionDurationMicros); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Timestamp != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Timestamp); + } + if (CallerIdentity.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(CallerIdentity); + } + if (functionCall_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FunctionCall); + } + if (Status != global::ClientApi.Event.Types.Status.Committed) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status); + } + if (Message.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); + } + if (EnergyQuantaUsed != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(EnergyQuantaUsed); + } + if (HostExecutionDurationMicros != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(HostExecutionDurationMicros); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Event other) { + if (other == null) { + return; + } + if (other.Timestamp != 0UL) { + Timestamp = other.Timestamp; + } + if (other.CallerIdentity.Length != 0) { + CallerIdentity = other.CallerIdentity; + } + if (other.functionCall_ != null) { + if (functionCall_ == null) { + FunctionCall = new global::ClientApi.FunctionCall(); + } + FunctionCall.MergeFrom(other.FunctionCall); + } + if (other.Status != global::ClientApi.Event.Types.Status.Committed) { + Status = other.Status; + } + if (other.Message.Length != 0) { + Message = other.Message; + } + if (other.EnergyQuantaUsed != 0L) { + EnergyQuantaUsed = other.EnergyQuantaUsed; + } + if (other.HostExecutionDurationMicros != 0UL) { + HostExecutionDurationMicros = other.HostExecutionDurationMicros; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Timestamp = input.ReadUInt64(); + break; + } + case 18: { + CallerIdentity = input.ReadBytes(); + break; + } + case 26: { + if (functionCall_ == null) { + FunctionCall = new global::ClientApi.FunctionCall(); + } + input.ReadMessage(FunctionCall); + break; + } + case 32: { + Status = (global::ClientApi.Event.Types.Status) input.ReadEnum(); + break; + } + case 42: { + Message = input.ReadString(); + break; + } + case 48: { + EnergyQuantaUsed = input.ReadInt64(); + break; + } + case 56: { + HostExecutionDurationMicros = input.ReadUInt64(); + break; + } + } + } + } + + #region Nested types + /// Container for nested types declared in the Event message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum Status { + [pbr::OriginalName("committed")] Committed = 0, + [pbr::OriginalName("failed")] Failed = 1, + [pbr::OriginalName("out_of_energy")] OutOfEnergy = 2, + } + + } + #endregion + + } + + /// + /// TODO: Maybe call this StateUpdate if it's implied to be a subscription update + /// + public sealed partial class SubscriptionUpdate : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubscriptionUpdate()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubscriptionUpdate() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubscriptionUpdate(SubscriptionUpdate other) : this() { + tableUpdates_ = other.tableUpdates_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubscriptionUpdate Clone() { + return new SubscriptionUpdate(this); + } + + /// Field number for the "tableUpdates" field. + public const int TableUpdatesFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_tableUpdates_codec + = pb::FieldCodec.ForMessage(10, global::ClientApi.TableUpdate.Parser); + private readonly pbc::RepeatedField tableUpdates_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField TableUpdates { + get { return tableUpdates_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SubscriptionUpdate); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SubscriptionUpdate other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!tableUpdates_.Equals(other.tableUpdates_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= tableUpdates_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + tableUpdates_.WriteTo(output, _repeated_tableUpdates_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += tableUpdates_.CalculateSize(_repeated_tableUpdates_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SubscriptionUpdate other) { + if (other == null) { + return; + } + tableUpdates_.Add(other.tableUpdates_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + tableUpdates_.AddEntriesFrom(input, _repeated_tableUpdates_codec); + break; + } + } + } + } + + } + + public sealed partial class TableUpdate : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TableUpdate()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TableUpdate() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TableUpdate(TableUpdate other) : this() { + tableId_ = other.tableId_; + tableName_ = other.tableName_; + tableRowOperations_ = other.tableRowOperations_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TableUpdate Clone() { + return new TableUpdate(this); + } + + /// Field number for the "tableId" field. + public const int TableIdFieldNumber = 1; + private uint tableId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint TableId { + get { return tableId_; } + set { + tableId_ = value; + } + } + + /// Field number for the "tableName" field. + public const int TableNameFieldNumber = 2; + private string tableName_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string TableName { + get { return tableName_; } + set { + tableName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "tableRowOperations" field. + public const int TableRowOperationsFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_tableRowOperations_codec + = pb::FieldCodec.ForMessage(26, global::ClientApi.TableRowOperation.Parser); + private readonly pbc::RepeatedField tableRowOperations_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField TableRowOperations { + get { return tableRowOperations_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TableUpdate); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TableUpdate other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (TableId != other.TableId) return false; + if (TableName != other.TableName) return false; + if(!tableRowOperations_.Equals(other.tableRowOperations_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (TableId != 0) hash ^= TableId.GetHashCode(); + if (TableName.Length != 0) hash ^= TableName.GetHashCode(); + hash ^= tableRowOperations_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (TableId != 0) { + output.WriteRawTag(8); + output.WriteUInt32(TableId); + } + if (TableName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(TableName); + } + tableRowOperations_.WriteTo(output, _repeated_tableRowOperations_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (TableId != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TableId); + } + if (TableName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(TableName); + } + size += tableRowOperations_.CalculateSize(_repeated_tableRowOperations_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TableUpdate other) { + if (other == null) { + return; + } + if (other.TableId != 0) { + TableId = other.TableId; + } + if (other.TableName.Length != 0) { + TableName = other.TableName; + } + tableRowOperations_.Add(other.tableRowOperations_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + TableId = input.ReadUInt32(); + break; + } + case 18: { + TableName = input.ReadString(); + break; + } + case 26: { + tableRowOperations_.AddEntriesFrom(input, _repeated_tableRowOperations_codec); + break; + } + } + } + } + + } + + public sealed partial class TableRowOperation : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TableRowOperation()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TableRowOperation() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TableRowOperation(TableRowOperation other) : this() { + op_ = other.op_; + rowPk_ = other.rowPk_; + row_ = other.row_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TableRowOperation Clone() { + return new TableRowOperation(this); + } + + /// Field number for the "op" field. + public const int OpFieldNumber = 1; + private global::ClientApi.TableRowOperation.Types.OperationType op_ = global::ClientApi.TableRowOperation.Types.OperationType.Delete; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.TableRowOperation.Types.OperationType Op { + get { return op_; } + set { + op_ = value; + } + } + + /// Field number for the "row_pk" field. + public const int RowPkFieldNumber = 2; + private pb::ByteString rowPk_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString RowPk { + get { return rowPk_; } + set { + rowPk_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "row" field. + public const int RowFieldNumber = 3; + private pb::ByteString row_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Row { + get { return row_; } + set { + row_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TableRowOperation); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TableRowOperation other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Op != other.Op) return false; + if (RowPk != other.RowPk) return false; + if (Row != other.Row) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) hash ^= Op.GetHashCode(); + if (RowPk.Length != 0) hash ^= RowPk.GetHashCode(); + if (Row.Length != 0) hash ^= Row.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { + output.WriteRawTag(8); + output.WriteEnum((int) Op); + } + if (RowPk.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(RowPk); + } + if (Row.Length != 0) { + output.WriteRawTag(26); + output.WriteBytes(Row); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Op); + } + if (RowPk.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(RowPk); + } + if (Row.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Row); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TableRowOperation other) { + if (other == null) { + return; + } + if (other.Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { + Op = other.Op; + } + if (other.RowPk.Length != 0) { + RowPk = other.RowPk; + } + if (other.Row.Length != 0) { + Row = other.Row; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Op = (global::ClientApi.TableRowOperation.Types.OperationType) input.ReadEnum(); + break; + } + case 18: { + RowPk = input.ReadBytes(); + break; + } + case 26: { + Row = input.ReadBytes(); + break; + } + } + } + } + + #region Nested types + /// Container for nested types declared in the TableRowOperation message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum OperationType { + [pbr::OriginalName("DELETE")] Delete = 0, + [pbr::OriginalName("INSERT")] Insert = 1, + } + + } + #endregion + + } + + public sealed partial class TransactionUpdate : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TransactionUpdate()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TransactionUpdate() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TransactionUpdate(TransactionUpdate other) : this() { + event_ = other.event_ != null ? other.event_.Clone() : null; + subscriptionUpdate_ = other.subscriptionUpdate_ != null ? other.subscriptionUpdate_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TransactionUpdate Clone() { + return new TransactionUpdate(this); + } + + /// Field number for the "event" field. + public const int EventFieldNumber = 1; + private global::ClientApi.Event event_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.Event Event { + get { return event_; } + set { + event_ = value; + } + } + + /// Field number for the "subscriptionUpdate" field. + public const int SubscriptionUpdateFieldNumber = 2; + private global::ClientApi.SubscriptionUpdate subscriptionUpdate_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ClientApi.SubscriptionUpdate SubscriptionUpdate { + get { return subscriptionUpdate_; } + set { + subscriptionUpdate_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TransactionUpdate); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TransactionUpdate other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Event, other.Event)) return false; + if (!object.Equals(SubscriptionUpdate, other.SubscriptionUpdate)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (event_ != null) hash ^= Event.GetHashCode(); + if (subscriptionUpdate_ != null) hash ^= SubscriptionUpdate.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (event_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Event); + } + if (subscriptionUpdate_ != null) { + output.WriteRawTag(18); + output.WriteMessage(SubscriptionUpdate); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (event_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Event); + } + if (subscriptionUpdate_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubscriptionUpdate); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TransactionUpdate other) { + if (other == null) { + return; + } + if (other.event_ != null) { + if (event_ == null) { + Event = new global::ClientApi.Event(); + } + Event.MergeFrom(other.Event); + } + if (other.subscriptionUpdate_ != null) { + if (subscriptionUpdate_ == null) { + SubscriptionUpdate = new global::ClientApi.SubscriptionUpdate(); + } + SubscriptionUpdate.MergeFrom(other.SubscriptionUpdate); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (event_ == null) { + Event = new global::ClientApi.Event(); + } + input.ReadMessage(Event); + break; + } + case 18: { + if (subscriptionUpdate_ == null) { + SubscriptionUpdate = new global::ClientApi.SubscriptionUpdate(); + } + input.ReadMessage(SubscriptionUpdate); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs.meta new file mode 100644 index 00000000000..2023804f8e7 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f4de68bfb39d5d4b8145d97dffde8c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs new file mode 100644 index 00000000000..8cf8f4dfdca --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs @@ -0,0 +1,5 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public interface IStdbTable { } \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs.meta new file mode 100644 index 00000000000..ab8e8b81237 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f969825278c8e3fd9014e02b825f7ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs new file mode 100644 index 00000000000..8d7f6b34e75 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel.Design; +using System.Linq; +using System.Net.Http.Headers; +using Google.Protobuf; +using UnityEngine; +using ClientApi; + +namespace SpacetimeDB +{ + public class StdbClientCache + { + public class TableCache + { + private class ByteArrayComparer : IEqualityComparer + { + public bool Equals(byte[] left, byte[] right) + { + if (left == null || right == null) + { + return left == right; + } + + return left.SequenceEqual(right); + } + + public int GetHashCode(byte[] key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + return key.Sum(b => b); + } + } + + private readonly string name; + private readonly TypeDef rowSchema; + + // The function to use for decoding a type value + private Func decoderFunc; + + // Maps from primary key to type value + public readonly Dictionary entries; + // Maps from primary key to decoded value + public readonly ConcurrentDictionary decodedValues; + + public TableCache(string name, TypeDef rowSchema, Func decoderFunc) + { + this.name = name; + this.rowSchema = rowSchema; + this.decoderFunc = decoderFunc; + entries = new Dictionary(new ByteArrayComparer()); + decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); + } + + public (TypeValue?, object) Decode(byte[] pk, TypeValue? value) + { + if (decodedValues.TryGetValue(pk, out var decoded)) + { + return decoded; + } + + if (!value.HasValue) + { + return (null, null); + } + decoded = (value.Value, decoderFunc(value.Value)); + decodedValues[pk] = decoded; + return decoded; + } + + public TypeDef GetSchema() => rowSchema; + + /// + /// Inserts the value into the table. There can be no existing value with the provided pk. + /// + /// + public object Insert(byte[] rowPk) + { + if (entries.TryGetValue(rowPk, out _)) + { + return null; + } + + var decodedTuple = Decode(rowPk, null); + if (decodedTuple.Item1.HasValue && decodedTuple.Item2 != null) + { + entries[rowPk] = (decodedTuple.Item1.Value, decodedTuple.Item2); + return decodedTuple.Item2; + } + + // Read failure + Debug.LogError($"Read error when converting row value for table: {name} (version issue?)"); + return null; + } + + /// + /// Updates an entry. Returns whether or not the update was successful. Updates only succeed if + /// a previous value was overwritten. + /// + /// The primary key that uniquely identifies this row + /// The new for the table entry + /// True when the old value was removed and the new value was inserted. + public bool Update(ByteString pk, ByteString newValueByteString) + { + // We have to figure out if pk is going to change or not + throw new InvalidOperationException(); + } + + /// + /// Deletes a value from the table. + /// + /// The primary key that uniquely identifies this row + /// + public object Delete(byte[] rowPk) + { + if (entries.TryGetValue(rowPk, out var value)) + { + entries.Remove(rowPk); + return value.Item2; + } + + return null; + } + } + + private readonly ConcurrentDictionary tables = new ConcurrentDictionary(); + + public void AddTable(string name, TypeDef tableRowDef, Func decodeFunc) + { + if (tables.TryGetValue(name, out _)) + { + Debug.LogError($"Table with name already exists: {name}"); + return; + } + + // Initialize this table + tables[name] = new TableCache(name, tableRowDef, decodeFunc); + } + public IEnumerable GetObjects(string name) + { + if (!tables.TryGetValue(name, out var table)) + { + yield break; + } + + foreach (var entry in table.entries) + { + yield return entry.Value.Item2; + } + } + + public IEnumerable GetEntries(string name) + { + if (!tables.TryGetValue(name, out var table)) + { + yield break; + } + + foreach (var entry in table.entries) + { + yield return entry.Value.Item1; + } + } + + public TableCache GetTable(string name) + { + if (tables.TryGetValue(name, out var table)) + { + return table; + } + + Debug.LogError($"We don't know that this table is: {name}"); + return null; + } + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs.meta new file mode 100644 index 00000000000..a95aebaeeee --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2ec50a3dcb5beb66e8728d6649ac3065 +timeCreated: 1658252769 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs new file mode 100644 index 00000000000..be6f809bc6c --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs @@ -0,0 +1,367 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using ClientApi; +using SpacetimeDB; +using UnityEngine; +using UnityEngine.Rendering; + +public class StdbNetworkManager : MonoBehaviour +{ + public enum TableOp + { + Insert, + Delete, + Update + } + + [Serializable] + public class Message + { + public string fn; + public object[] args; + } + + private struct DbEvent + { + public string tableName; + public TableOp op; + public object oldValue; + public object newValue; + } + + [SerializeField] private float clientTicksPerSecond = 30.0f; + + public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue); + + public event Action onConnect; + public event Action onDisconnect; + public event Action clientTick; + + /// + /// Invoked on each row update to each table. + /// + public event RowUpdate tableUpdate; + + /// + /// Callback is invoked after a transaction or subscription update is received and all updates have been applied. + /// + public event Action onRowUpdateComplete; + + /// + /// Called when we receive an identity from the server + /// + public event Action onIdentityReceived; + + /// + /// Invoked when an event message is received or at the end of a transaction update. + /// + public event Action onEvent; + + private WebSocketDispatch.WebSocket webSocket; + private bool connectionClosed; + public static StdbClientCache clientDB; + + private float? lastClientTick; + public static float clientTickInterval; + + private Thread messageProcessThread; + + public static StdbNetworkManager instance; + + protected void Awake() + { + if (instance != null) + { + Debug.LogError($"There is more than one {GetType()}"); + return; + } + + instance = this; + + var options = new WebSocketDispatch.ConnectOptions + { + //v1.bin.spacetimedb + //v1.text.spacetimedb + Protocol = "v1.bin.spacetimedb", + }; + webSocket = new WebSocketDispatch.WebSocket(options); + webSocket.OnMessage += OnMessageReceived; + webSocket.OnClose += status => onDisconnect?.Invoke(); + webSocket.OnConnect += () => onConnect?.Invoke(); + + clientDB = new StdbClientCache(); + + var type = typeof(IStdbTable); + var types = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(s => s.GetTypes()) + .Where(p => type.IsAssignableFrom(p)); + foreach (var @class in types) + { + if (!@class.IsClass) + { + continue; + } + var typeDefFunc = @class.GetMethod("GetTypeDef", BindingFlags.Static | BindingFlags.Public); + var typeDef = typeDefFunc!.Invoke(null, null) as TypeDef; + // var conversionFunc = @class.GetMethod("op_Explicit"); + var conversionFunc = @class.GetMethods().FirstOrDefault(a => + a.Name == "op_Explicit" && a.GetParameters().Length > 0 && + a.GetParameters()[0].ParameterType == typeof(TypeValue)); + clientDB.AddTable(@class.Name, typeDef, a => + { + return conversionFunc!.Invoke(null, new object[] { a }); + }); + } + + messageProcessThread = new Thread(ProcessMessages); + messageProcessThread.Start(); + clientTickInterval = 1 / clientTicksPerSecond; + } + + private readonly BlockingCollection _messageQueue = new BlockingCollection(); + private readonly ConcurrentQueue _completedMessages = new ConcurrentQueue(); + + void ProcessMessages() + { + while (true) + { + var bytes = _messageQueue.Take(); + + var message = ClientApi.Message.Parser.ParseFrom(bytes); + SubscriptionUpdate subscriptionUpdate = null; + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + subscriptionUpdate = message.SubscriptionUpdate; + break; + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; + break; + } + + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + // First apply all of the state + System.Diagnostics.Debug.Assert(subscriptionUpdate != null, nameof(subscriptionUpdate) + " != null"); + foreach (var update in subscriptionUpdate.TableUpdates) + { + foreach (var row in update.TableRowOperations) + { + var table = clientDB.GetTable(update.TableName); + var typeDef = table.GetSchema(); + var (typeValue, _) = TypeValue.Decode(typeDef, row.Row); + if (typeValue.HasValue) + { + // Here we are decoding on our message thread so that by the time we get to the + // main thread the cache is already warm. + table.Decode(row.RowPk.ToByteArray(), typeValue.Value); + } + } + } + break; + } + + _completedMessages.Enqueue(bytes); + } + } + + private void OnDestroy() + { + connectionClosed = true; + webSocket.Close(); + webSocket = null; + } + + public void Connect(string host, string address) + { + var token = PlayerPrefs.HasKey(GetTokenKey()) ? PlayerPrefs.GetString(GetTokenKey()) : null; + + Task.Run(async () => + { + try + { + await webSocket.Connect(token, host, address); + } + catch (Exception e) + { + if (connectionClosed) + { + Debug.Log("Connection closed gracefully."); + return; + } + + Debug.LogException(e); + } + }); + } + + readonly List _dbEvents = new List(); + private void OnMessageProcessComplete(byte[] bytes) + { + _dbEvents.Clear(); + var message = ClientApi.Message.Parser.ParseFrom(bytes); + + SubscriptionUpdate subscriptionUpdate = null; + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + subscriptionUpdate = message.SubscriptionUpdate; + break; + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; + break; + } + + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + // First apply all of the state + foreach (var update in subscriptionUpdate.TableUpdates) + { + var tableName = update.TableName; + var table = clientDB.GetTable(tableName); + if (table == null) + { + continue; + } + + foreach (var row in update.TableRowOperations) + { + var rowPk = row.RowPk.ToByteArray(); + + switch (row.Op) + { + case TableRowOperation.Types.OperationType.Delete: + var deletedValue = table.Delete(rowPk); + if (deletedValue != null) + { + _dbEvents.Add(new DbEvent + { + tableName = tableName, + op = TableOp.Delete, + newValue = null, + oldValue = deletedValue, + }); + } + + break; + case TableRowOperation.Types.OperationType.Insert: + var insertedValue = table.Insert(rowPk); + if (insertedValue != null) + { + _dbEvents.Add(new DbEvent + { + tableName = tableName, + op = TableOp.Insert, + newValue = insertedValue, + oldValue = null + }); + } + + break; + } + } + } + + // Send out events + var eventCount = _dbEvents.Count; + for (int i = 0; i < eventCount; i++) + { + bool isUpdate = false; + if (i < eventCount - 1) + { + if (_dbEvents[i].op == TableOp.Delete && _dbEvents[i + 1].op == TableOp.Insert) + { + // somewhat hacky: Delete followed by an insert on the same table is considered an update. + isUpdate = _dbEvents[i].tableName.Equals(_dbEvents[i + 1].tableName); + } + } + + if (isUpdate) + { + // Merge delete and insert in one update + tableUpdate?.Invoke(_dbEvents[i].tableName, TableOp.Update, _dbEvents[i].oldValue, + _dbEvents[i + 1].newValue); + i++; + } + else + { + tableUpdate?.Invoke(_dbEvents[i].tableName, _dbEvents[i].op, _dbEvents[i].oldValue, + _dbEvents[i].newValue); + } + } + + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + onRowUpdateComplete?.Invoke(); + break; + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + onRowUpdateComplete?.Invoke(); + onEvent?.Invoke(message.TransactionUpdate.Event); + break; + } + + break; + case ClientApi.Message.TypeOneofCase.IdentityToken: + onIdentityReceived?.Invoke(Hash.From(message.IdentityToken.Identity.ToByteArray())); + PlayerPrefs.SetString(GetTokenKey(), message.IdentityToken.Token); + break; + case ClientApi.Message.TypeOneofCase.Event: + onEvent?.Invoke(message.Event); + break; + } + } + + + private void OnMessageReceived(byte[] bytes) => _messageQueue.Add(bytes); + + private string GetTokenKey() + { + var key = "bitcraftmini.identity_token"; +#if UNITY_EDITOR + // Different editors need different keys + key += $" - {Application.dataPath}"; +#endif + return key; + } + + internal void InternalCallReducer(Message message) + { + var json = Newtonsoft.Json.JsonConvert.SerializeObject(message); + webSocket.Send(Encoding.ASCII.GetBytes(json)); + } + + private void Update() + { + webSocket.Update(); + + if (!lastClientTick.HasValue) + { + lastClientTick = Time.time; + } + else + { + if (Time.time - lastClientTick > clientTickInterval) + { + lastClientTick = Time.time; + clientTick?.Invoke(); + } + } + + while (_completedMessages.TryDequeue(out var result)) + { + OnMessageProcessComplete(result); + } + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs.meta new file mode 100644 index 00000000000..cc9f8c5c528 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afbc59781ed95141abe2453be650b4bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs new file mode 100644 index 00000000000..1daa8ec9494 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs @@ -0,0 +1,496 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Google.Protobuf; +using UnityEngine; + +namespace SpacetimeDB +{ + public class TypeDef + { + public enum Def + { + Tuple = 0, + Enum, + + // base types + Vec, + U8, + U16, + U32, + U64, + U128, + I8, + I16, + I32, + I64, + I128, + Bool, + F32, + F64, + String, + Bytes, + Hash, + Unit, + } + + public Def Type => type; + public ElementDef[] TupleElements => tupleElements; + + public TypeDef VecMemberType => vecMemberType; + + public Def type; + private TypeDef vecMemberType; + public ElementDef[] tupleElements; + + public static TypeDef GetVec(TypeDef memberType) + { + return new TypeDef + { + type = Def.Vec, + vecMemberType = memberType, + }; + } + + public static TypeDef BuiltInType(Def def) + { + switch (def) + { + case Def.Tuple: + case Def.Enum: + case Def.Vec: + Debug.LogError("This is not a built-in type"); + break; + } + + return new TypeDef + { + type = def, + }; + } + + public static TypeDef Tuple(ElementDef[] elements) + { + return new TypeDef + { + type = Def.Tuple, + tupleElements = elements, + }; + } + } + + public struct ElementDef + { + public byte tag; + public TypeDef element; + + public ElementDef(byte tag, TypeDef element) + { + this.tag = tag; + this.element = element; + } + } + + public struct TypeValue + { + public class TypeValueComparer : IEqualityComparer + { + public bool Equals(TypeValue value1, TypeValue value2) + { + if (value1.typeDef.Type != value2.typeDef.Type) + { + return false; + } + + // Handle any strange cases + switch (value1.typeDef.Type) + { + case TypeDef.Def.Tuple: + if ((value1.tupleElements == null) != (value2.tupleElements == null)) + { + return false; + } + + if (value1.tupleElements == null) + { + break; + } + + if (value1.tupleElements.Length != value2.tupleElements.Length) + { + return false; + } + + break; + } + + return true; + } + + public int GetHashCode(TypeValue obj) + { + switch (obj.typeDef.Type) + { + case TypeDef.Def.Bool: + return (int)(obj.b ? 0xab745abf : 0xf60d5833); + case TypeDef.Def.Bytes: + if (obj.bytes == null) + { + throw new InvalidOperationException("Cannot hash on null bytes."); + } + + return (int)(obj.bytes.GetHashCode() ^ 0x8595a70b); + case TypeDef.Def.Enum: + throw new NotImplementedException(); + case TypeDef.Def.F32: + case TypeDef.Def.F64: + throw new InvalidOperationException("Cannot hash on floats"); + case TypeDef.Def.Hash: + return (int)(obj.hash.GetHashCode() ^ 0x8595a70b); + case TypeDef.Def.I8: + return (int)(obj.signed ^ 0x6bac6c4e); + case TypeDef.Def.I16: + return (int)(obj.signed ^ 0x2b4e01bf); + case TypeDef.Def.I32: + return (int)(obj.signed ^ 0xe32a7812); + case TypeDef.Def.I64: + return (int)(obj.signed ^ 0xab745abf ^ (obj.signed >> 32)); + case TypeDef.Def.U8: + return (int)(obj.unsigned ^ 0xc2964a29); + case TypeDef.Def.U16: + return (int)(obj.unsigned ^ 0xfb504320); + case TypeDef.Def.U32: + return (int)(obj.unsigned ^ 0x74208545); + case TypeDef.Def.U64: + return (int)(obj.unsigned ^ 0x3ef90ce5 ^ (obj.unsigned >> 32)); + case TypeDef.Def.I128: + case TypeDef.Def.U128: + throw new InvalidOperationException("Hashing on 128 bit integers unsupported"); + case TypeDef.Def.String: + if (obj.str == null) + { + throw new InvalidOperationException("Cannot hash on null string."); + } + + return obj.str.GetHashCode() ^ 0x33e1b1f4; + case TypeDef.Def.Tuple: + { + var hash = (int)(obj.tupleElements.Length ^ 0xbbce67bf); + foreach (var element in obj.tupleElements) + { + hash ^= element.GetHashCode(); + } + + return hash; + } + case TypeDef.Def.Unit: + return 0x64b22bc4; + case TypeDef.Def.Vec: + var vecHash = 0x0fec85d5; + foreach (var value in obj.vec) + { + vecHash ^= value.GetHashCode(); + } + + return vecHash; + } + + throw new NotImplementedException($"Hashing on: {obj.typeDef.Type}"); + } + } + + public TypeDef TypeDef => typeDef; + + private TypeDef typeDef; + private ulong unsigned; + private long signed; + private string str; + private byte[] bytes; + private Hash hash; + private bool b; + + private float f32; + private double f64; + private TypeValue[] tupleElements; + private List vec; + + public override string ToString() + { + if (tupleElements != null) { + var s = "(\n"; + foreach (var e in tupleElements) { + s += "\t"; + s += e.ToString(); + s += "\n"; + } + s += ")"; + return s; + } else { + return String.Format($"typeDef={typeDef.Type}, unsigned={unsigned}, signed={signed}, str={str}, bytes={bytes}, bool={b}, float={f32}, double={f64}"); + } + } + + public static (TypeValue?, int) Decode(TypeDef def, ByteString bytes) + { + var b = bytes[1]; + var byteArr = bytes.ToByteArray(); + return Decode(def, byteArr, 0, byteArr.Length); + } + + public static (TypeValue?, int) Decode(TypeDef def, byte[] arr, int offset, int length) + { + var value = new TypeValue + { + typeDef = def + }; + var read = 0; + + try + { + switch (def.Type) + { + case TypeDef.Def.Bool: + value.b = arr[offset] != 0; + read = 1; + break; + case TypeDef.Def.U8: + value.unsigned = arr[offset]; + read = 1; + break; + case TypeDef.Def.U16: + value.unsigned = BitConverter.ToUInt16(arr, offset); + read = 2; + break; + case TypeDef.Def.U32: + value.unsigned = BitConverter.ToUInt32(arr, offset); + read = 4; + break; + case TypeDef.Def.U64: + value.unsigned = BitConverter.ToUInt64(arr, offset); + read = 8; + break; + case TypeDef.Def.I8: + value.signed = arr[offset]; + read = 1; + break; + case TypeDef.Def.I16: + value.signed = BitConverter.ToInt16(arr, offset); + read = 2; + break; + case TypeDef.Def.I32: + value.signed = BitConverter.ToInt32(arr, offset); + read = 4; + break; + case TypeDef.Def.I64: + value.signed = BitConverter.ToInt64(arr, offset); + read = 8; + break; + case TypeDef.Def.F32: + value.f32 = BitConverter.ToSingle(arr, offset); + read = 4; + break; + case TypeDef.Def.F64: + value.f64 = BitConverter.ToDouble(arr, offset); + read = 8; + break; + case TypeDef.Def.String: + var strLength = BitConverter.ToUInt16(arr, offset); + value.str = Encoding.UTF8.GetString(arr, offset + 2, strLength); + read += strLength + 2; + break; + case TypeDef.Def.Bytes: + var byteLength = BitConverter.ToUInt16(arr, offset); + if (byteLength >= arr.Length - (offset + 2)) + { + throw new InvalidOperationException( + $"Read error: byte array goes past the end of the array: {byteLength}"); + } + + value.bytes = new byte[byteLength]; + Array.Copy(arr, offset + 2, value.bytes, 0, byteLength); + read += byteLength + 2; + break; + case TypeDef.Def.Hash: + byte[] hashVal = new byte[Hash.SIZE]; + Array.Copy(arr, offset, hashVal, 0, Hash.SIZE); + read += Hash.SIZE; + value.hash = Hash.From(hashVal); + break; + case TypeDef.Def.Tuple: + return ReadTuple(def, arr, offset, length); + case TypeDef.Def.Vec: + if (def.VecMemberType == null) + { + throw new InvalidOperationException("Read error: vec has no member type!"); + } + + var vecLength = BitConverter.ToUInt16(arr, offset); + read += 2; + value.vec = new List(); + for (var idx = 0; idx < vecLength; idx++) + { + var (entry, subDecodeRead) = Decode(def.VecMemberType, arr, offset + read, length); + read += subDecodeRead; + if (entry.HasValue) + { + value.vec.Add(entry.Value); + } + } + + break; + default: + Debug.LogError($"This type is unsupported for now: {def.Type}"); + return (null, 0); + } + } + catch (Exception e) + { + Debug.LogException(e); + Debug.LogError("Are your table definitions in BitCraftMiniGameManager correct?"); + return (null, 0); + } + + return (value, read); + } + + private static (TypeValue?, int) ReadTuple(TypeDef def, byte[] arr, int offset, int length) + { + var read = 0; + var resultElements = new TypeValue[def.TupleElements.Length]; + var elementIdx = 0; + foreach (var elementDef in def.TupleElements) + { + var (value, bytesRead) = Decode(elementDef.element, arr, offset + read, length); + + if (!value.HasValue) + { + return (null, 0); + } + + read += bytesRead; + resultElements[elementIdx++] = value.Value; + } + + return (GetTuple(def, resultElements), read); + } + + public object GetValue(TypeDef.Def def) + { + switch (def) + { + case TypeDef.Def.Bool: + return b; + case TypeDef.Def.U8: + return (byte)unsigned; + case TypeDef.Def.U16: + return (ushort)unsigned; + case TypeDef.Def.U32: + return (uint)unsigned; + case TypeDef.Def.U64: + return unsigned; + case TypeDef.Def.U128: + throw new InvalidOperationException("U128 not supported in C#"); + + case TypeDef.Def.I8: + return (byte)signed; + case TypeDef.Def.I16: + return (ushort)signed; + case TypeDef.Def.I32: + return (int)signed; + case TypeDef.Def.I64: + return signed; + case TypeDef.Def.I128: + throw new InvalidOperationException("I128 not supported in C#"); + + case TypeDef.Def.String: + return str; + case TypeDef.Def.Bytes: + if (bytes == null) + throw new InvalidOperationException("byte array is null!"); + return bytes; + case TypeDef.Def.Hash: + return hash; + case TypeDef.Def.F32: + return f32; + case TypeDef.Def.F64: + return f64; + case TypeDef.Def.Tuple: + return tupleElements; + case TypeDef.Def.Vec: + return vec; + } + + throw new InvalidOperationException($"Type not supported yet! {def}"); + } + + public object GetValue(TypeDef def) + { + return GetValue(def.Type); + } + + public static TypeValue GetTuple(TypeDef def, TypeValue[] tupleValues) + { + return new TypeValue + { + typeDef = def, + tupleElements = tupleValues, + }; + } + + public static TypeValue GetVec(TypeDef memberType, IEnumerable values) + { + return new TypeValue + { + typeDef = TypeDef.GetVec(memberType), + vec = new List(values), + }; + } + } + + public struct Hash : IEquatable + { + private byte[] bytes; + + public static int SIZE = 32; + + public byte[] Bytes => bytes; + + public static TypeDef GetTypeDef() + { + return TypeDef.BuiltInType(TypeDef.Def.Hash); + } + + public static explicit operator Hash(TypeValue v) => (Hash)v.GetValue(GetTypeDef()); + + public static Hash From(byte[] bytes) + { + // TODO: should we validate length here? + return new Hash + { + bytes = bytes, + }; + } + + public bool Equals(Hash other) + { + return bytes.SequenceEqual(other.bytes); + } + + public override bool Equals(object o) { + return o is Hash other && Equals(other); + } + + public static bool operator ==(Hash a, Hash b) => a.Equals(b); + public static bool operator !=(Hash a, Hash b) => !a.Equals(b); + + public override int GetHashCode() { + if (bytes == null) + { + throw new InvalidOperationException("Cannot hash on null bytes."); + } + + return bytes.GetHashCode(); + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs.meta new file mode 100644 index 00000000000..7306cba35a6 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6ebc8a2d7cebaea6e9e6bd87e94781bd +timeCreated: 1657552127 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs new file mode 100644 index 00000000000..ecef71d71de --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; + +namespace WebSocketDispatch +{ + internal abstract class MainThreadDispatch + { + public abstract void Execute(); + } + + class OnConnectMessage : MainThreadDispatch + { + private WebSocketOpenEventHandler receiver; + + public OnConnectMessage(WebSocketOpenEventHandler receiver) + { + this.receiver = receiver; + } + + public override void Execute() + { + receiver.Invoke(); + } + } + + class OnDisconnectMessage : MainThreadDispatch + { + private WebSocketCloseEventHandler receiver; + private WebSocketCloseStatus? status; + + public OnDisconnectMessage(WebSocketCloseEventHandler receiver, WebSocketCloseStatus? status) + { + this.receiver = receiver; + this.status = status; + } + + public override void Execute() + { + receiver.Invoke(status); + } + } + + class OnMessage : MainThreadDispatch + { + private WebSocketMessageEventHandler receiver; + private byte[] message; + + public OnMessage(WebSocketMessageEventHandler receiver, byte[] message) + { + this.receiver = receiver; + this.message = message; + } + + public override void Execute() + { + receiver.Invoke(message); + } + } + + public delegate void WebSocketOpenEventHandler(); + + public delegate void WebSocketMessageEventHandler(byte[] message); + + public delegate void WebSocketErrorEventHandler(string errorMsg); + + public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? closeCode); + + public struct ConnectOptions + { + public string Protocol; + } + + + public class WebSocket + { + // WebSocket buffer for incoming messages + private static readonly int MAXMessageSize = 0x2000000; // 32MB + + // Connection parameters + private readonly ConnectOptions _options; + private readonly byte[] _receiveBuffer = new byte[MAXMessageSize]; + private readonly ConcurrentQueue dispatchQueue = new ConcurrentQueue(); + + protected ClientWebSocket Ws; + + public WebSocket(ConnectOptions options) + { + Ws = new ClientWebSocket(); + _options = options; + } + + public event WebSocketOpenEventHandler OnConnect; + public event WebSocketMessageEventHandler OnMessage; + public event WebSocketCloseEventHandler OnClose; + + public async Task Connect(string auth, string host, string address) + { + var url = new Uri($"ws://{host}/database/subscribe/{address}"); + Ws.Options.AddSubProtocol(_options.Protocol); + + var source = new CancellationTokenSource(10000); + if (!string.IsNullOrEmpty(auth)) + { + var tokenBytes = Encoding.UTF8.GetBytes($"token:{auth}"); + var base64 = Convert.ToBase64String(tokenBytes); + Ws.Options.SetRequestHeader("Authorization", "Basic " + base64); + } + else + { + Ws.Options.UseDefaultCredentials = true; + } + + try + { + await Ws.ConnectAsync(url, source.Token); + dispatchQueue.Enqueue(new OnConnectMessage(OnConnect)); + } + catch (WebSocketException ex) + { + if (ex.WebSocketErrorCode == WebSocketError.UnsupportedProtocol) + { + Debug.LogError("Unsupported protocol."); + return; + } + + Debug.LogError("Error connecting: " + ex); + return; + } + catch (Exception e) + { + Debug.LogError("Other error: " + e); + return; + } + + while (Ws.State == WebSocketState.Open) + { + try + { + var receiveResult = await Ws.ReceiveAsync(new ArraySegment(_receiveBuffer), + CancellationToken.None); + if (receiveResult.MessageType == WebSocketMessageType.Close) + { + await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, + CancellationToken.None); + if (receiveResult.CloseStatus != WebSocketCloseStatus.NormalClosure) + { + Debug.LogError("Server closed connection abnormally."); + dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, receiveResult.CloseStatus)); + } + } + else + { + var count = receiveResult.Count; + while (receiveResult.EndOfMessage == false) + { + if (count >= MAXMessageSize) + { + var closeMessage = $"Maximum message size: {MAXMessageSize} bytes."; + await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, + CancellationToken.None); + return; + } + + receiveResult = await Ws.ReceiveAsync( + new ArraySegment(_receiveBuffer, count, MAXMessageSize - count), + CancellationToken.None); + count += receiveResult.Count; + } + + var buffCopy = new byte[count]; + for (var x = 0; x < count; x++) + buffCopy[x] = _receiveBuffer[x]; + dispatchQueue.Enqueue(new OnMessage(OnMessage, buffCopy)); + } + } + catch (WebSocketException ex) + { + if (ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) + { + Debug.LogError("Server closed connection prematurely."); + dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, null)); + break; + } + + Debug.LogError(ex); + } + } + } + + public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure, string reason = null) + { + Ws?.CloseAsync(code, "Disconnecting normally.", CancellationToken.None); + Ws = null; + + return Task.CompletedTask; + } + + private readonly object sendingLock = new object(); + private Task senderTask = null; + private readonly ConcurrentQueue messageSendQueue = new ConcurrentQueue(); + + /// + /// This sender guarantees that that messages are sent out in the order they are received. Our websocket + /// library only allows us to await one send call, so we have to wait until the current send call is complete + /// before we start another one. This function is also thread safe, just in case. + /// + /// The message to send + public void Send(byte[] message) + { + lock (messageSendQueue) + { + messageSendQueue.Enqueue(message); + if (senderTask == null) + { + senderTask = Task.Run(async () => { await ProcessSendQueue(); }); + } + } + } + + + private async Task ProcessSendQueue() + { + while (true) + { + byte[] message; + lock (messageSendQueue) + { + if (!messageSendQueue.TryDequeue(out message)) + { + // We are out of messages to send + senderTask = null; + return; + } + } + + await Ws!.SendAsync(new ArraySegment(message), WebSocketMessageType.Text, true, + CancellationToken.None); + } + } + + public WebSocketState GetState() + { + return Ws!.State; + } + + public void Update() + { + while (dispatchQueue.TryDequeue(out var result)) + { + result.Execute(); + } + } + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs.meta new file mode 100644 index 00000000000..afff70f5a2a --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0e36b7f4e40f850758fc453d53de0fbc +timeCreated: 1656515225 \ No newline at end of file diff --git a/sdks/csharp/Packages/manifest.json b/sdks/csharp/Packages/manifest.json new file mode 100644 index 00000000000..137e47eada5 --- /dev/null +++ b/sdks/csharp/Packages/manifest.json @@ -0,0 +1,44 @@ +{ + "dependencies": { + "com.unity.collab-proxy": "1.15.4", + "com.unity.ide.rider": "2.0.7", + "com.unity.ide.visualstudio": "2.0.12", + "com.unity.ide.vscode": "1.2.4", + "com.unity.render-pipelines.universal": "10.7.0", + "com.unity.test-framework": "1.1.29", + "com.unity.textmeshpro": "3.0.6", + "com.unity.timeline": "1.4.8", + "com.unity.ugui": "1.0.0", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/sdks/csharp/Packages/packages-lock.json b/sdks/csharp/Packages/packages-lock.json new file mode 100644 index 00000000000..984ab05e058 --- /dev/null +++ b/sdks/csharp/Packages/packages-lock.json @@ -0,0 +1,403 @@ +{ + "dependencies": { + "com.unity.collab-proxy": { + "version": "1.15.4", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.nuget.newtonsoft-json": "2.0.0", + "com.unity.services.core": "1.0.1" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ext.nunit": { + "version": "1.0.6", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ide.rider": { + "version": "2.0.7", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.1" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.visualstudio": { + "version": "2.0.12", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.9" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.vscode": { + "version": "1.2.4", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.mathematics": { + "version": "1.1.0", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.nuget.newtonsoft-json": { + "version": "2.0.0", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.render-pipelines.core": { + "version": "10.7.0", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.ugui": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.render-pipelines.universal": { + "version": "10.7.0", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.mathematics": "1.1.0", + "com.unity.render-pipelines.core": "10.7.0", + "com.unity.shadergraph": "10.7.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.searcher": { + "version": "4.3.2", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.services.core": { + "version": "1.0.1", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.shadergraph": { + "version": "10.7.0", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.render-pipelines.core": "10.7.0", + "com.unity.searcher": "4.3.2" + }, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework": { + "version": "1.1.29", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.textmeshpro": { + "version": "3.0.6", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ugui": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.timeline": { + "version": "1.4.8", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.modules.director": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ugui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0" + } + }, + "com.unity.modules.ai": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.androidjni": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.animation": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.assetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.audio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.cloth": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.director": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.animation": "1.0.0" + } + }, + "com.unity.modules.imageconversion": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.imgui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.jsonserialize": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.particlesystem": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics2d": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.screencapture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.subsystems": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.terrain": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.terrainphysics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.terrain": "1.0.0" + } + }, + "com.unity.modules.tilemap": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics2d": "1.0.0" + } + }, + "com.unity.modules.ui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.uielements": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.uielementsnative": "1.0.0" + } + }, + "com.unity.modules.uielementsnative": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.umbra": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unityanalytics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.unitywebrequest": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unitywebrequestassetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestaudio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.audio": "1.0.0" + } + }, + "com.unity.modules.unitywebrequesttexture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestwww": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.vehicles": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.video": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.vr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } + }, + "com.unity.modules.wind": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.xr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.subsystems": "1.0.0" + } + } + } +} diff --git a/sdks/csharp/ProjectSettings/AudioManager.asset b/sdks/csharp/ProjectSettings/AudioManager.asset new file mode 100644 index 00000000000..27287fec5f4 --- /dev/null +++ b/sdks/csharp/ProjectSettings/AudioManager.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 + m_RequestedDSPBufferSize: 0 diff --git a/sdks/csharp/ProjectSettings/ClusterInputManager.asset b/sdks/csharp/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 00000000000..e7886b266a0 --- /dev/null +++ b/sdks/csharp/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/sdks/csharp/ProjectSettings/DynamicsManager.asset b/sdks/csharp/ProjectSettings/DynamicsManager.asset new file mode 100644 index 00000000000..5d5bacb2a5e --- /dev/null +++ b/sdks/csharp/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0.1 + m_ClothInterCollisionStiffness: 0.2 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 0 + m_ReuseCollisionCallbacks: 1 + m_ClothInterCollisionSettingsToggle: 0 + m_ClothGravity: {x: 0, y: -9.81, z: 0} + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 + m_FrictionType: 0 + m_EnableEnhancedDeterminism: 0 + m_EnableUnifiedHeightmaps: 1 + m_SolverType: 0 + m_DefaultMaxAngularSpeed: 7 diff --git a/sdks/csharp/ProjectSettings/EditorBuildSettings.asset b/sdks/csharp/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 00000000000..2a4cbc567e2 --- /dev/null +++ b/sdks/csharp/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: + - enabled: 1 + path: Assets/Scenes/SampleScene.unity + guid: d1c3109bdb54ad54c8a2b2838528e640 + m_configObjects: {} diff --git a/sdks/csharp/ProjectSettings/EditorSettings.asset b/sdks/csharp/ProjectSettings/EditorSettings.asset new file mode 100644 index 00000000000..05db6c812e9 --- /dev/null +++ b/sdks/csharp/ProjectSettings/EditorSettings.asset @@ -0,0 +1,31 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_AssetPipelineMode: 1 + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 0 + m_DefaultBehaviorMode: 0 + m_PrefabRegularEnvironment: {fileID: 0} + m_PrefabUIEnvironment: {fileID: 0} + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp + m_ProjectGenerationRootNamespace: + m_CollabEditorSettings: + inProgressEnabled: 1 + m_EnableTextureStreamingInEditMode: 1 + m_EnableTextureStreamingInPlayMode: 1 + m_AsyncShaderCompilation: 1 + m_EnterPlayModeOptionsEnabled: 0 + m_EnterPlayModeOptions: 3 + m_ShowLightmapResolutionOverlay: 1 + m_UseLegacyProbeSampleCount: 0 + m_SerializeInlineMappingsOnOneLine: 1 diff --git a/sdks/csharp/ProjectSettings/GraphicsSettings.asset b/sdks/csharp/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 00000000000..db10dd6de06 --- /dev/null +++ b/sdks/csharp/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,68 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 11400000, guid: 19ba41d7c0026c3459d37c2fe90c55a0, + type: 2} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 1 + m_LightsUseColorTemperature: 0 + m_LogWhenShaderIsCompiled: 0 + m_AllowEnlightenSupportForUpgradedProject: 1 diff --git a/sdks/csharp/ProjectSettings/InputManager.asset b/sdks/csharp/ProjectSettings/InputManager.asset new file mode 100644 index 00000000000..b16147e954f --- /dev/null +++ b/sdks/csharp/ProjectSettings/InputManager.asset @@ -0,0 +1,487 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Enable Debug Button 1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: joystick button 8 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Enable Debug Button 2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: backspace + altNegativeButton: + altPositiveButton: joystick button 9 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Reset + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Next + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: page down + altNegativeButton: + altPositiveButton: joystick button 5 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Previous + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: page up + altNegativeButton: + altPositiveButton: joystick button 4 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Validate + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Persistent + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: right shift + altNegativeButton: + altPositiveButton: joystick button 2 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Multiplier + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: joystick button 3 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 2 + axis: 6 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 2 + axis: 5 + joyNum: 0 diff --git a/sdks/csharp/ProjectSettings/NavMeshAreas.asset b/sdks/csharp/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 00000000000..3b0b7c3d183 --- /dev/null +++ b/sdks/csharp/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/sdks/csharp/ProjectSettings/PackageManagerSettings.asset b/sdks/csharp/ProjectSettings/PackageManagerSettings.asset new file mode 100644 index 00000000000..be4a7974ec1 --- /dev/null +++ b/sdks/csharp/ProjectSettings/PackageManagerSettings.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_EnablePreviewPackages: 0 + m_EnablePackageDependencies: 0 + m_AdvancedSettingsExpanded: 1 + m_ScopedRegistriesSettingsExpanded: 1 + oneTimeWarningShown: 0 + m_Registries: + - m_Id: main + m_Name: + m_Url: https://packages.unity.com + m_Scopes: [] + m_IsDefault: 1 + m_Capabilities: 7 + m_UserSelectedRegistryName: + m_UserAddingNewScopedRegistry: 0 + m_RegistryInfoDraft: + m_ErrorMessage: + m_Original: + m_Id: + m_Name: + m_Url: + m_Scopes: [] + m_IsDefault: 0 + m_Capabilities: 0 + m_Modified: 0 + m_Name: + m_Url: + m_Scopes: + - + m_SelectedScopeIndex: 0 diff --git a/sdks/csharp/ProjectSettings/Physics2DSettings.asset b/sdks/csharp/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 00000000000..47880b1c8c8 --- /dev/null +++ b/sdks/csharp/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,56 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 4 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_JobOptions: + serializedVersion: 2 + useMultithreading: 0 + useConsistencySorting: 0 + m_InterpolationPosesPerJob: 100 + m_NewContactsPerJob: 30 + m_CollideContactsPerJob: 100 + m_ClearFlagsPerJob: 200 + m_ClearBodyForcesPerJob: 200 + m_SyncDiscreteFixturesPerJob: 50 + m_SyncContinuousFixturesPerJob: 50 + m_FindNearestContactsPerJob: 100 + m_UpdateTriggerContactsPerJob: 100 + m_IslandSolverCostThreshold: 100 + m_IslandSolverBodyCostScale: 1 + m_IslandSolverContactCostScale: 10 + m_IslandSolverJointCostScale: 10 + m_IslandSolverBodiesPerJob: 50 + m_IslandSolverContactsPerJob: 50 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_CallbacksOnDisable: 1 + m_ReuseCollisionCallbacks: 1 + m_AutoSyncTransforms: 0 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/sdks/csharp/ProjectSettings/PresetManager.asset b/sdks/csharp/ProjectSettings/PresetManager.asset new file mode 100644 index 00000000000..10a1b07384a --- /dev/null +++ b/sdks/csharp/ProjectSettings/PresetManager.asset @@ -0,0 +1,27 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + m_DefaultList: + - type: + m_NativeTypeID: 108 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + defaultPresets: + - m_Preset: {fileID: 2655988077585873504, guid: 463065d4f17d1d94d848aa127b94dd43, + type: 2} + - type: + m_NativeTypeID: 1020 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + defaultPresets: + - m_Preset: {fileID: 2655988077585873504, guid: e7689051185d12f4298e1ebb2693a29f, + type: 2} + - type: + m_NativeTypeID: 1006 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + defaultPresets: + - m_Preset: {fileID: 2655988077585873504, guid: e8537455c6c08bd4e8bf0be3707da685, + type: 2} diff --git a/sdks/csharp/ProjectSettings/ProjectSettings.asset b/sdks/csharp/ProjectSettings/ProjectSettings.asset new file mode 100644 index 00000000000..4a28a37ec73 --- /dev/null +++ b/sdks/csharp/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,698 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 22 + productGUID: ab1ec9304db0f00cba3d0fdd5dffedf9 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: SpacetimeUnitySDK + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1920 + defaultScreenHeight: 1080 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 1 + m_MTRendering: 1 + mipStripping: 0 + numberOfMipsStripped: 0 + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosUseCustomAppBackgroundBehavior: 0 + iosAllowHTTPDownload: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 0 + androidUseSwappy: 1 + androidBlitType: 1 + androidResizableWindow: 0 + androidDefaultWindowWidth: 1920 + androidDefaultWindowHeight: 1080 + androidMinimumWindowWidth: 400 + androidMinimumWindowHeight: 300 + androidFullscreenMode: 1 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 1 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + useFlipModelSwapchain: 1 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 1 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 0 + switchQueueControlMemory: 0 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + vulkanEnablePreTransform: 0 + vulkanEnableLateAcquireNextImage: 0 + vulkanEnableCommandBufferRecycling: 1 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleVersion: 0.1 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + enable360StereoCapture: 0 + isWsaHolographicRemotingEnabled: 0 + enableFrameTimingStats: 0 + useHDRDisplay: 0 + D3DHDRBitDepth: 0 + m_ColorGamuts: 0000000003000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: {} + buildNumber: + Standalone: 0 + iPhone: 0 + tvOS: 0 + overrideDefaultApplicationIdentifier: 0 + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 19 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 0 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 11.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 11.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSLaunchScreenCustomStoryboardPath: + iOSLaunchScreeniPadCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + iosCopyPluginsCodeInsteadOfSymlink: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + shaderPrecisionModel: 0 + clonedFromGUID: 9870af204204ab84596f8a656f2f2ce6 + templatePackageId: com.unity.template.universal@10.7.0 + templateDefaultScene: Assets/Scenes/SampleScene.unity + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 0 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 0 + useCustomProguardFile: 0 + AndroidTargetArchitectures: 1 + AndroidTargetDevices: 0 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 0 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + chromeosInputEmulation: 1 + AndroidMinifyWithR8: 0 + AndroidMinifyRelease: 0 + AndroidMinifyDebug: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 100 + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: [] + m_BuildTargetBatching: + - m_BuildTarget: Standalone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: tvOS + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: iPhone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: Android + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: WebGL + m_StaticBatching: 0 + m_DynamicBatching: 0 + m_BuildTargetGraphicsJobs: + - m_BuildTarget: MacStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: Switch + m_GraphicsJobs: 1 + - m_BuildTarget: MetroSupport + m_GraphicsJobs: 1 + - m_BuildTarget: AppleTVSupport + m_GraphicsJobs: 0 + - m_BuildTarget: BJMSupport + m_GraphicsJobs: 1 + - m_BuildTarget: LinuxStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: PS4Player + m_GraphicsJobs: 1 + - m_BuildTarget: iOSSupport + m_GraphicsJobs: 0 + - m_BuildTarget: WindowsStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobs: 1 + - m_BuildTarget: LuminSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AndroidPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: WebGLSupport + m_GraphicsJobs: 0 + m_BuildTargetGraphicsJobMode: + - m_BuildTarget: PS4Player + m_GraphicsJobMode: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobMode: 0 + m_BuildTargetGraphicsAPIs: + - m_BuildTarget: iOSSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AppleTVSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AndroidPlayer + m_APIs: 150000000b000000 + m_Automatic: 0 + - m_BuildTarget: WebGLSupport + m_APIs: 0b000000 + m_Automatic: 0 + m_BuildTargetVRSettings: [] + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + openGLRequireES32: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: + - m_BuildTarget: Standalone + m_EncodingQuality: 1 + m_BuildTargetGroupLightmapSettings: [] + m_BuildTargetNormalMapEncoding: [] + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + bluetoothUsageDescription: + switchNMETAOverride: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchUseGOLDLinker: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchTitleNames_15: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchPublisherNames_15: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchIcons_15: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchSmallIcons_15: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchTouchScreenUsage: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchRatingsInt_12: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 22 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + switchUseNewStyleFilepaths: 0 + switchUseMicroSleepForYield: 1 + switchMicroSleepForYieldTime: 25 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 1 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 0 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4AllowPS5Detection: 0 + ps4GPU800MHz: 1 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: + - libc.prx + - libSceAudioLatencyEstimation.prx + - libSceFace.prx + - libSceFaceTracker.prx + - libSceFios2.prx + - libSceHand.prx + - libSceHandTracker.prx + - libSceHeadTracker.prx + - libSceJobManager.prx + - libSceNpToolkit2.prx + - libSceS3DConversion.prx + ps4attribVROutputEnabled: 0 + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 + spritePackerPolicy: + webGLMemorySize: 16 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLWasmArithmeticExceptions: 0 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLDecompressionFallback: 0 + scriptingDefineSymbols: {} + additionalCompilerArguments: {} + platformArchitecture: {} + scriptingBackend: + Standalone: 0 + il2cppCompilerConfiguration: {} + managedStrippingLevel: {} + incrementalIl2cppBuild: {} + suppressCommonWarnings: 1 + allowUnsafeCode: 0 + useDeterministicCompilation: 1 + useReferenceAssemblies: 1 + enableRoslynAnalyzers: 1 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 1 + assemblyVersionValidation: 1 + gcWBarrierValidation: 0 + apiCompatibilityLevelPerPlatform: + Standalone: 3 + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: Template_Lightweight + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: Template_Lightweight + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnhancedXboxCompatibilityMode: 0 + XboxOneEnableGPUVariability: 1 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + XboxOneOverrideIdentityName: + XboxOneOverrideIdentityPublisher: + vrEditorSettings: {} + cloudServicesEnabled: + UNet: 1 + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + apiCompatibilityLevel: 6 + activeInputHandler: 0 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + qualitySettingsNames: [] + projectName: + organizationId: + cloudEnabled: 0 + legacyClampBlendShapeWeights: 0 + virtualTexturingSupportEnabled: 0 diff --git a/sdks/csharp/ProjectSettings/ProjectVersion.txt b/sdks/csharp/ProjectSettings/ProjectVersion.txt new file mode 100644 index 00000000000..4c9401b919c --- /dev/null +++ b/sdks/csharp/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2020.3.25f1 +m_EditorVersionWithRevision: 2020.3.25f1 (9b9180224418) diff --git a/sdks/csharp/ProjectSettings/QualitySettings.asset b/sdks/csharp/ProjectSettings/QualitySettings.asset new file mode 100644 index 00000000000..dad5d50cfff --- /dev/null +++ b/sdks/csharp/ProjectSettings/QualitySettings.asset @@ -0,0 +1,128 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 2 + m_QualitySettings: + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + skinWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 11400000, guid: a31e9f9f9c9d4b9429ed0d1234e22103, type: 2} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + skinWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 11400000, guid: d847b876476d3d6468f5dfcd34266f96, type: 2} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + skinWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 2 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 11400000, guid: 19ba41d7c0026c3459d37c2fe90c55a0, type: 2} + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 1 + Lumin: 2 + Nintendo Switch: 2 + PS4: 2 + Stadia: 2 + Standalone: 2 + WebGL: 1 + Windows Store Apps: 2 + XboxOne: 2 + iPhone: 1 + tvOS: 1 diff --git a/sdks/csharp/ProjectSettings/SceneTemplateSettings.json b/sdks/csharp/ProjectSettings/SceneTemplateSettings.json new file mode 100644 index 00000000000..6f3e60fd8b7 --- /dev/null +++ b/sdks/csharp/ProjectSettings/SceneTemplateSettings.json @@ -0,0 +1,167 @@ +{ + "templatePinStates": [], + "dependencyTypeInfos": [ + { + "userAdded": false, + "type": "UnityEngine.AnimationClip", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.Animations.AnimatorController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.AnimatorOverrideController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.Audio.AudioMixerController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.ComputeShader", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Cubemap", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.GameObject", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.LightingDataAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": false + }, + { + "userAdded": false, + "type": "UnityEngine.LightingSettings", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Material", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.MonoScript", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicMaterial", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicsMaterial2D", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.VolumeProfile", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.SceneAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": false + }, + { + "userAdded": false, + "type": "UnityEngine.Shader", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.ShaderVariantCollection", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Texture", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Texture2D", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Timeline.TimelineAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + } + ], + "defaultDependencyTypeInfo": { + "userAdded": false, + "type": "", + "ignore": false, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + "newSceneOverride": 0 +} \ No newline at end of file diff --git a/sdks/csharp/ProjectSettings/TagManager.asset b/sdks/csharp/ProjectSettings/TagManager.asset new file mode 100644 index 00000000000..1c92a7840ec --- /dev/null +++ b/sdks/csharp/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/sdks/csharp/ProjectSettings/TimeManager.asset b/sdks/csharp/ProjectSettings/TimeManager.asset new file mode 100644 index 00000000000..06bcc6d2953 --- /dev/null +++ b/sdks/csharp/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.1 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/sdks/csharp/ProjectSettings/URPProjectSettings.asset b/sdks/csharp/ProjectSettings/URPProjectSettings.asset new file mode 100644 index 00000000000..3077404f36b --- /dev/null +++ b/sdks/csharp/ProjectSettings/URPProjectSettings.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3} + m_Name: + m_EditorClassIdentifier: + m_LastMaterialVersion: 4 diff --git a/sdks/csharp/ProjectSettings/UnityConnectSettings.asset b/sdks/csharp/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 00000000000..6125b308af4 --- /dev/null +++ b/sdks/csharp/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 1 + m_Enabled: 0 + m_TestMode: 0 + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_DashboardUrl: https://dashboard.unity3d.com + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com + m_Enabled: 0 + m_LogBufferSize: 10 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_TestMode: 0 + m_InitializeOnStartup: 1 + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/sdks/csharp/ProjectSettings/VFXManager.asset b/sdks/csharp/ProjectSettings/VFXManager.asset new file mode 100644 index 00000000000..6e0eaca40d5 --- /dev/null +++ b/sdks/csharp/ProjectSettings/VFXManager.asset @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!937362698 &1 +VFXManager: + m_ObjectHideFlags: 0 + m_IndirectShader: {fileID: 0} + m_CopyBufferShader: {fileID: 0} + m_SortShader: {fileID: 0} + m_RenderPipeSettingsPath: + m_FixedTimeStep: 0.016666668 + m_MaxDeltaTime: 0.05 diff --git a/sdks/csharp/ProjectSettings/VersionControlSettings.asset b/sdks/csharp/ProjectSettings/VersionControlSettings.asset new file mode 100644 index 00000000000..dca288142fc --- /dev/null +++ b/sdks/csharp/ProjectSettings/VersionControlSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!890905787 &1 +VersionControlSettings: + m_ObjectHideFlags: 0 + m_Mode: Visible Meta Files + m_CollabEditorSettings: + inProgressEnabled: 1 diff --git a/sdks/csharp/ProjectSettings/XRSettings.asset b/sdks/csharp/ProjectSettings/XRSettings.asset new file mode 100644 index 00000000000..482590c196f --- /dev/null +++ b/sdks/csharp/ProjectSettings/XRSettings.asset @@ -0,0 +1,10 @@ +{ + "m_SettingKeys": [ + "VR Device Disabled", + "VR Device User Alert" + ], + "m_SettingValues": [ + "False", + "False" + ] +} \ No newline at end of file diff --git a/sdks/csharp/export.sh b/sdks/csharp/export.sh new file mode 100644 index 00000000000..67767301448 --- /dev/null +++ b/sdks/csharp/export.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +if [ -z "$UNITY_PATH" ]; then + export UNITY_PATH="~/Unity/Hub/Editor/2020.3.25f1/Editor/Unity" +fi + +if [ ! -f $UNITY_PATH ]; then + echo "Unable to find a version of Unity. Please specify it using UNITY_PATH :)" +fi + +$UNITY_PATH -projectPath . -quit -batchmode -nographics -ignorecompilererrors -executeMethod "ExportPackage.Export" From 77b7c27807722da8aaa3c59328067b875b095114 Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Tue, 1 Nov 2022 14:10:15 +0000 Subject: [PATCH 002/223] chmod +x export.sh --- sdks/csharp/export.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 sdks/csharp/export.sh diff --git a/sdks/csharp/export.sh b/sdks/csharp/export.sh old mode 100644 new mode 100755 From 6c014f68eedf2862f445a845457a5c630cd348ff Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Tue, 1 Nov 2022 14:34:17 +0000 Subject: [PATCH 003/223] Renamed arguments for connect. Changed connection URI to use URL parameter. --- .../Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs | 9 +++++++-- sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs index be6f809bc6c..626495abb87 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs @@ -181,7 +181,12 @@ private void OnDestroy() webSocket = null; } - public void Connect(string host, string address) + /// + /// Connect to a remote spacetime instance. + /// + /// The host or IP address and the port to connect to. Example: spacetime.spacetimedb.net:3000 + /// The name or address of the database to connect to + public void Connect(string host, string addressOrName) { var token = PlayerPrefs.HasKey(GetTokenKey()) ? PlayerPrefs.GetString(GetTokenKey()) : null; @@ -189,7 +194,7 @@ public void Connect(string host, string address) { try { - await webSocket.Connect(token, host, address); + await webSocket.Connect(token, host, addressOrName); } catch (Exception e) { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs index ecef71d71de..a9332ac8e2c 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs @@ -99,9 +99,9 @@ public WebSocket(ConnectOptions options) public event WebSocketMessageEventHandler OnMessage; public event WebSocketCloseEventHandler OnClose; - public async Task Connect(string auth, string host, string address) + public async Task Connect(string auth, string host, string nameOrAddress) { - var url = new Uri($"ws://{host}/database/subscribe/{address}"); + var url = new Uri($"ws://{host}/database/subscribe?name_or_address={nameOrAddress}"); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000); From 1f4f10b655a53fc68b3248df7b8c4b092a22bf34 Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Tue, 1 Nov 2022 18:44:57 +0000 Subject: [PATCH 004/223] Fix export script --- sdks/csharp/export.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/sdks/csharp/export.sh b/sdks/csharp/export.sh index 67767301448..0233d344050 100755 --- a/sdks/csharp/export.sh +++ b/sdks/csharp/export.sh @@ -6,6 +6,7 @@ fi if [ ! -f $UNITY_PATH ]; then echo "Unable to find a version of Unity. Please specify it using UNITY_PATH :)" + exit 1 fi $UNITY_PATH -projectPath . -quit -batchmode -nographics -ignorecompilererrors -executeMethod "ExportPackage.Export" From e6670fe3e85ea0eb90daf7f84af55c7f13db1904 Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Tue, 1 Nov 2022 18:46:04 +0000 Subject: [PATCH 005/223] Another fix to export script --- sdks/csharp/export.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/export.sh b/sdks/csharp/export.sh index 0233d344050..de896251153 100755 --- a/sdks/csharp/export.sh +++ b/sdks/csharp/export.sh @@ -1,7 +1,7 @@ #!/bin/bash if [ -z "$UNITY_PATH" ]; then - export UNITY_PATH="~/Unity/Hub/Editor/2020.3.25f1/Editor/Unity" + export UNITY_PATH="$HOME/Unity/Hub/Editor/2020.3.25f1/Editor/Unity" fi if [ ! -f $UNITY_PATH ]; then From 5ac9a7e25b9ff29d762641a7334673acc22c810c Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Wed, 2 Nov 2022 10:37:43 +0000 Subject: [PATCH 006/223] Remove BitCraftMini from the SDK --- .../csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs | 2 +- sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs index 626495abb87..03d17f3b0a5 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs @@ -333,7 +333,7 @@ private void OnMessageProcessComplete(byte[] bytes) private string GetTokenKey() { - var key = "bitcraftmini.identity_token"; + var key = "spacetimedb.identity_token"; #if UNITY_EDITOR // Different editors need different keys key += $" - {Application.dataPath}"; diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs index 1daa8ec9494..1883e3ad26f 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs @@ -231,14 +231,14 @@ public override string ToString() } } - public static (TypeValue?, int) Decode(TypeDef def, ByteString bytes) + internal static (TypeValue?, int) Decode(TypeDef def, ByteString bytes) { var b = bytes[1]; var byteArr = bytes.ToByteArray(); return Decode(def, byteArr, 0, byteArr.Length); } - public static (TypeValue?, int) Decode(TypeDef def, byte[] arr, int offset, int length) + internal static (TypeValue?, int) Decode(TypeDef def, byte[] arr, int offset, int length) { var value = new TypeValue { @@ -347,7 +347,7 @@ public static (TypeValue?, int) Decode(TypeDef def, byte[] arr, int offset, int catch (Exception e) { Debug.LogException(e); - Debug.LogError("Are your table definitions in BitCraftMiniGameManager correct?"); + Debug.LogError("Please report this error in the SpacetimeDB discord."); return (null, 0); } From ee0380193ef5eb213da083c7e5fdd560195872c3 Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Wed, 2 Nov 2022 11:57:20 +0000 Subject: [PATCH 007/223] Some API updates --- .../{StdbClientCache.cs => ClientCache.cs} | 2 +- ...lientCache.cs.meta => ClientCache.cs.meta} | 0 .../{IStdbTable.cs => IDatabaseTable.cs} | 5 +- ...dbTable.cs.meta => IDatabaseTable.cs.meta} | 0 .../SpacetimeDB/Scripts/NetworkManager.cs | 371 +++++++++++++++++ ...Manager.cs.meta => NetworkManager.cs.meta} | 0 .../SpacetimeDB/Scripts/StdbNetworkManager.cs | 372 ------------------ .../Assets/SpacetimeDB/Scripts/WebSocket.cs | 95 ++--- 8 files changed, 427 insertions(+), 418 deletions(-) rename sdks/csharp/Assets/SpacetimeDB/Scripts/{StdbClientCache.cs => ClientCache.cs} (99%) rename sdks/csharp/Assets/SpacetimeDB/Scripts/{StdbClientCache.cs.meta => ClientCache.cs.meta} (100%) rename sdks/csharp/Assets/SpacetimeDB/Scripts/{IStdbTable.cs => IDatabaseTable.cs} (55%) rename sdks/csharp/Assets/SpacetimeDB/Scripts/{IStdbTable.cs.meta => IDatabaseTable.cs.meta} (100%) create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs rename sdks/csharp/Assets/SpacetimeDB/Scripts/{StdbNetworkManager.cs.meta => NetworkManager.cs.meta} (100%) delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs similarity index 99% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs rename to sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index 8d7f6b34e75..bcb381b20ec 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -10,7 +10,7 @@ namespace SpacetimeDB { - public class StdbClientCache + public class ClientCache { public class TableCache { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs.meta similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/StdbClientCache.cs.meta rename to sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs similarity index 55% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs rename to sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs index 8cf8f4dfdca..ec8c06f8f66 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs @@ -2,4 +2,7 @@ using System.Collections.Generic; using UnityEngine; -public interface IStdbTable { } \ No newline at end of file +namespace SpacetimeDB +{ + public interface IDatabaseTable { } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs.meta similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/IStdbTable.cs.meta rename to sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs new file mode 100644 index 00000000000..077123afcf4 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -0,0 +1,371 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Net.WebSockets; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using ClientApi; +using SpacetimeDB; +using UnityEngine; + +namespace SpacetimeDB +{ + public class NetworkManager : MonoBehaviour + { + public enum TableOp + { + Insert, + Delete, + Update + } + + [Serializable] + public class Message + { + public string fn; + public object[] args; + } + + private struct DbEvent + { + public string tableName; + public TableOp op; + public object oldValue; + public object newValue; + } + + public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue); + + /// + /// Called when a connection is established to a spacetimedb instance. + /// + public event Action onConnect; + + /// + /// Called when a connection attempt fails. + /// + public event Action onConnectError; + + /// + /// Called when a connection that was established has disconnected. + /// + public event Action onDisconnect; + + /// + /// Invoked on each row update to each table. + /// + public event RowUpdate tableUpdate; + + /// + /// Callback is invoked after a transaction or subscription update is received and all updates have been applied. + /// + public event Action onRowUpdateComplete; + + /// + /// Called when we receive an identity from the server + /// + public event Action onIdentityReceived; + + /// + /// Invoked when an event message is received or at the end of a transaction update. + /// + public event Action onEvent; + + private WebSocketDispatch.WebSocket webSocket; + private bool connectionClosed; + public static ClientCache clientDB; + + private float? lastClientTick; + public static float clientTickInterval; + + private Thread messageProcessThread; + + public static NetworkManager instance; + + protected void Awake() + { + if (instance != null) + { + Debug.LogError($"There is more than one {GetType()}"); + return; + } + + instance = this; + + var options = new WebSocketDispatch.ConnectOptions + { + //v1.bin.spacetimedb + //v1.text.spacetimedb + Protocol = "v1.bin.spacetimedb", + }; + webSocket = new WebSocketDispatch.WebSocket(options); + webSocket.OnMessage += OnMessageReceived; + webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); + webSocket.OnConnect += () => onConnect?.Invoke(); + + clientDB = new ClientCache(); + + var type = typeof(IDatabaseTable); + var types = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(s => s.GetTypes()) + .Where(p => type.IsAssignableFrom(p)); + foreach (var @class in types) + { + if (!@class.IsClass) + { + continue; + } + + var typeDefFunc = @class.GetMethod("GetTypeDef", BindingFlags.Static | BindingFlags.Public); + var typeDef = typeDefFunc!.Invoke(null, null) as TypeDef; + // var conversionFunc = @class.GetMethod("op_Explicit"); + var conversionFunc = @class.GetMethods().FirstOrDefault(a => + a.Name == "op_Explicit" && a.GetParameters().Length > 0 && + a.GetParameters()[0].ParameterType == typeof(TypeValue)); + clientDB.AddTable(@class.Name, typeDef, + a => { return conversionFunc!.Invoke(null, new object[] { a }); }); + } + + messageProcessThread = new Thread(ProcessMessages); + messageProcessThread.Start(); + } + + private readonly BlockingCollection _messageQueue = new BlockingCollection(); + private readonly ConcurrentQueue _completedMessages = new ConcurrentQueue(); + + void ProcessMessages() + { + while (true) + { + var bytes = _messageQueue.Take(); + + var message = ClientApi.Message.Parser.ParseFrom(bytes); + SubscriptionUpdate subscriptionUpdate = null; + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + subscriptionUpdate = message.SubscriptionUpdate; + break; + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; + break; + } + + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + // First apply all of the state + System.Diagnostics.Debug.Assert(subscriptionUpdate != null, + nameof(subscriptionUpdate) + " != null"); + foreach (var update in subscriptionUpdate.TableUpdates) + { + foreach (var row in update.TableRowOperations) + { + var table = clientDB.GetTable(update.TableName); + var typeDef = table.GetSchema(); + var (typeValue, _) = TypeValue.Decode(typeDef, row.Row); + if (typeValue.HasValue) + { + // Here we are decoding on our message thread so that by the time we get to the + // main thread the cache is already warm. + table.Decode(row.RowPk.ToByteArray(), typeValue.Value); + } + } + } + + break; + } + + _completedMessages.Enqueue(bytes); + } + } + + private void OnDestroy() + { + connectionClosed = true; + webSocket.Close(); + webSocket = null; + } + + /// + /// Connect to a remote spacetime instance. + /// + /// The host or IP address and the port to connect to. Example: spacetime.spacetimedb.net:3000 + /// The name or address of the database to connect to + public void Connect(string host, string addressOrName) + { + var token = PlayerPrefs.HasKey(GetTokenKey()) ? PlayerPrefs.GetString(GetTokenKey()) : null; + + Task.Run(async () => + { + try + { + await webSocket.Connect(token, host, addressOrName); + } + catch (Exception e) + { + if (connectionClosed) + { + Debug.Log("Connection closed gracefully."); + return; + } + + Debug.LogException(e); + } + }); + } + + readonly List _dbEvents = new List(); + + private void OnMessageProcessComplete(byte[] bytes) + { + _dbEvents.Clear(); + var message = ClientApi.Message.Parser.ParseFrom(bytes); + + SubscriptionUpdate subscriptionUpdate = null; + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + subscriptionUpdate = message.SubscriptionUpdate; + break; + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; + break; + } + + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + // First apply all of the state + foreach (var update in subscriptionUpdate.TableUpdates) + { + var tableName = update.TableName; + var table = clientDB.GetTable(tableName); + if (table == null) + { + continue; + } + + foreach (var row in update.TableRowOperations) + { + var rowPk = row.RowPk.ToByteArray(); + + switch (row.Op) + { + case TableRowOperation.Types.OperationType.Delete: + var deletedValue = table.Delete(rowPk); + if (deletedValue != null) + { + _dbEvents.Add(new DbEvent + { + tableName = tableName, + op = TableOp.Delete, + newValue = null, + oldValue = deletedValue, + }); + } + + break; + case TableRowOperation.Types.OperationType.Insert: + var insertedValue = table.Insert(rowPk); + if (insertedValue != null) + { + _dbEvents.Add(new DbEvent + { + tableName = tableName, + op = TableOp.Insert, + newValue = insertedValue, + oldValue = null + }); + } + + break; + } + } + } + + // Send out events + var eventCount = _dbEvents.Count; + for (int i = 0; i < eventCount; i++) + { + bool isUpdate = false; + if (i < eventCount - 1) + { + if (_dbEvents[i].op == TableOp.Delete && _dbEvents[i + 1].op == TableOp.Insert) + { + // somewhat hacky: Delete followed by an insert on the same table is considered an update. + isUpdate = _dbEvents[i].tableName.Equals(_dbEvents[i + 1].tableName); + } + } + + if (isUpdate) + { + // Merge delete and insert in one update + tableUpdate?.Invoke(_dbEvents[i].tableName, TableOp.Update, _dbEvents[i].oldValue, + _dbEvents[i + 1].newValue); + i++; + } + else + { + tableUpdate?.Invoke(_dbEvents[i].tableName, _dbEvents[i].op, _dbEvents[i].oldValue, + _dbEvents[i].newValue); + } + } + + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + onRowUpdateComplete?.Invoke(); + break; + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + onRowUpdateComplete?.Invoke(); + onEvent?.Invoke(message.TransactionUpdate.Event); + break; + } + + break; + case ClientApi.Message.TypeOneofCase.IdentityToken: + onIdentityReceived?.Invoke(Hash.From(message.IdentityToken.Identity.ToByteArray())); + PlayerPrefs.SetString(GetTokenKey(), message.IdentityToken.Token); + break; + case ClientApi.Message.TypeOneofCase.Event: + onEvent?.Invoke(message.Event); + break; + } + } + + + private void OnMessageReceived(byte[] bytes) => _messageQueue.Add(bytes); + + private string GetTokenKey() + { + var key = "spacetimedb.identity_token"; +#if UNITY_EDITOR + // Different editors need different keys + key += $" - {Application.dataPath}"; +#endif + return key; + } + + internal void InternalCallReducer(Message message) + { + var json = Newtonsoft.Json.JsonConvert.SerializeObject(message); + webSocket.Send(Encoding.ASCII.GetBytes(json)); + } + + private void Update() + { + webSocket.Update(); + + while (_completedMessages.TryDequeue(out var result)) + { + OnMessageProcessComplete(result); + } + } + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs.meta similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs.meta rename to sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs deleted file mode 100644 index 03d17f3b0a5..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/StdbNetworkManager.cs +++ /dev/null @@ -1,372 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using ClientApi; -using SpacetimeDB; -using UnityEngine; -using UnityEngine.Rendering; - -public class StdbNetworkManager : MonoBehaviour -{ - public enum TableOp - { - Insert, - Delete, - Update - } - - [Serializable] - public class Message - { - public string fn; - public object[] args; - } - - private struct DbEvent - { - public string tableName; - public TableOp op; - public object oldValue; - public object newValue; - } - - [SerializeField] private float clientTicksPerSecond = 30.0f; - - public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue); - - public event Action onConnect; - public event Action onDisconnect; - public event Action clientTick; - - /// - /// Invoked on each row update to each table. - /// - public event RowUpdate tableUpdate; - - /// - /// Callback is invoked after a transaction or subscription update is received and all updates have been applied. - /// - public event Action onRowUpdateComplete; - - /// - /// Called when we receive an identity from the server - /// - public event Action onIdentityReceived; - - /// - /// Invoked when an event message is received or at the end of a transaction update. - /// - public event Action onEvent; - - private WebSocketDispatch.WebSocket webSocket; - private bool connectionClosed; - public static StdbClientCache clientDB; - - private float? lastClientTick; - public static float clientTickInterval; - - private Thread messageProcessThread; - - public static StdbNetworkManager instance; - - protected void Awake() - { - if (instance != null) - { - Debug.LogError($"There is more than one {GetType()}"); - return; - } - - instance = this; - - var options = new WebSocketDispatch.ConnectOptions - { - //v1.bin.spacetimedb - //v1.text.spacetimedb - Protocol = "v1.bin.spacetimedb", - }; - webSocket = new WebSocketDispatch.WebSocket(options); - webSocket.OnMessage += OnMessageReceived; - webSocket.OnClose += status => onDisconnect?.Invoke(); - webSocket.OnConnect += () => onConnect?.Invoke(); - - clientDB = new StdbClientCache(); - - var type = typeof(IStdbTable); - var types = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(s => s.GetTypes()) - .Where(p => type.IsAssignableFrom(p)); - foreach (var @class in types) - { - if (!@class.IsClass) - { - continue; - } - var typeDefFunc = @class.GetMethod("GetTypeDef", BindingFlags.Static | BindingFlags.Public); - var typeDef = typeDefFunc!.Invoke(null, null) as TypeDef; - // var conversionFunc = @class.GetMethod("op_Explicit"); - var conversionFunc = @class.GetMethods().FirstOrDefault(a => - a.Name == "op_Explicit" && a.GetParameters().Length > 0 && - a.GetParameters()[0].ParameterType == typeof(TypeValue)); - clientDB.AddTable(@class.Name, typeDef, a => - { - return conversionFunc!.Invoke(null, new object[] { a }); - }); - } - - messageProcessThread = new Thread(ProcessMessages); - messageProcessThread.Start(); - clientTickInterval = 1 / clientTicksPerSecond; - } - - private readonly BlockingCollection _messageQueue = new BlockingCollection(); - private readonly ConcurrentQueue _completedMessages = new ConcurrentQueue(); - - void ProcessMessages() - { - while (true) - { - var bytes = _messageQueue.Take(); - - var message = ClientApi.Message.Parser.ParseFrom(bytes); - SubscriptionUpdate subscriptionUpdate = null; - switch (message.TypeCase) - { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - subscriptionUpdate = message.SubscriptionUpdate; - break; - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; - break; - } - - switch (message.TypeCase) - { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - // First apply all of the state - System.Diagnostics.Debug.Assert(subscriptionUpdate != null, nameof(subscriptionUpdate) + " != null"); - foreach (var update in subscriptionUpdate.TableUpdates) - { - foreach (var row in update.TableRowOperations) - { - var table = clientDB.GetTable(update.TableName); - var typeDef = table.GetSchema(); - var (typeValue, _) = TypeValue.Decode(typeDef, row.Row); - if (typeValue.HasValue) - { - // Here we are decoding on our message thread so that by the time we get to the - // main thread the cache is already warm. - table.Decode(row.RowPk.ToByteArray(), typeValue.Value); - } - } - } - break; - } - - _completedMessages.Enqueue(bytes); - } - } - - private void OnDestroy() - { - connectionClosed = true; - webSocket.Close(); - webSocket = null; - } - - /// - /// Connect to a remote spacetime instance. - /// - /// The host or IP address and the port to connect to. Example: spacetime.spacetimedb.net:3000 - /// The name or address of the database to connect to - public void Connect(string host, string addressOrName) - { - var token = PlayerPrefs.HasKey(GetTokenKey()) ? PlayerPrefs.GetString(GetTokenKey()) : null; - - Task.Run(async () => - { - try - { - await webSocket.Connect(token, host, addressOrName); - } - catch (Exception e) - { - if (connectionClosed) - { - Debug.Log("Connection closed gracefully."); - return; - } - - Debug.LogException(e); - } - }); - } - - readonly List _dbEvents = new List(); - private void OnMessageProcessComplete(byte[] bytes) - { - _dbEvents.Clear(); - var message = ClientApi.Message.Parser.ParseFrom(bytes); - - SubscriptionUpdate subscriptionUpdate = null; - switch (message.TypeCase) - { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - subscriptionUpdate = message.SubscriptionUpdate; - break; - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; - break; - } - - switch (message.TypeCase) - { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - // First apply all of the state - foreach (var update in subscriptionUpdate.TableUpdates) - { - var tableName = update.TableName; - var table = clientDB.GetTable(tableName); - if (table == null) - { - continue; - } - - foreach (var row in update.TableRowOperations) - { - var rowPk = row.RowPk.ToByteArray(); - - switch (row.Op) - { - case TableRowOperation.Types.OperationType.Delete: - var deletedValue = table.Delete(rowPk); - if (deletedValue != null) - { - _dbEvents.Add(new DbEvent - { - tableName = tableName, - op = TableOp.Delete, - newValue = null, - oldValue = deletedValue, - }); - } - - break; - case TableRowOperation.Types.OperationType.Insert: - var insertedValue = table.Insert(rowPk); - if (insertedValue != null) - { - _dbEvents.Add(new DbEvent - { - tableName = tableName, - op = TableOp.Insert, - newValue = insertedValue, - oldValue = null - }); - } - - break; - } - } - } - - // Send out events - var eventCount = _dbEvents.Count; - for (int i = 0; i < eventCount; i++) - { - bool isUpdate = false; - if (i < eventCount - 1) - { - if (_dbEvents[i].op == TableOp.Delete && _dbEvents[i + 1].op == TableOp.Insert) - { - // somewhat hacky: Delete followed by an insert on the same table is considered an update. - isUpdate = _dbEvents[i].tableName.Equals(_dbEvents[i + 1].tableName); - } - } - - if (isUpdate) - { - // Merge delete and insert in one update - tableUpdate?.Invoke(_dbEvents[i].tableName, TableOp.Update, _dbEvents[i].oldValue, - _dbEvents[i + 1].newValue); - i++; - } - else - { - tableUpdate?.Invoke(_dbEvents[i].tableName, _dbEvents[i].op, _dbEvents[i].oldValue, - _dbEvents[i].newValue); - } - } - - switch (message.TypeCase) - { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - onRowUpdateComplete?.Invoke(); - break; - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - onRowUpdateComplete?.Invoke(); - onEvent?.Invoke(message.TransactionUpdate.Event); - break; - } - - break; - case ClientApi.Message.TypeOneofCase.IdentityToken: - onIdentityReceived?.Invoke(Hash.From(message.IdentityToken.Identity.ToByteArray())); - PlayerPrefs.SetString(GetTokenKey(), message.IdentityToken.Token); - break; - case ClientApi.Message.TypeOneofCase.Event: - onEvent?.Invoke(message.Event); - break; - } - } - - - private void OnMessageReceived(byte[] bytes) => _messageQueue.Add(bytes); - - private string GetTokenKey() - { - var key = "spacetimedb.identity_token"; -#if UNITY_EDITOR - // Different editors need different keys - key += $" - {Application.dataPath}"; -#endif - return key; - } - - internal void InternalCallReducer(Message message) - { - var json = Newtonsoft.Json.JsonConvert.SerializeObject(message); - webSocket.Send(Encoding.ASCII.GetBytes(json)); - } - - private void Update() - { - webSocket.Update(); - - if (!lastClientTick.HasValue) - { - lastClientTick = Time.time; - } - else - { - if (Time.time - lastClientTick > clientTickInterval) - { - lastClientTick = Time.time; - clientTick?.Invoke(); - } - } - - while (_completedMessages.TryDequeue(out var result)) - { - OnMessageProcessComplete(result); - } - } -} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs index a9332ac8e2c..4af79c9d54e 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs @@ -32,17 +32,37 @@ public override void Execute() class OnDisconnectMessage : MainThreadDispatch { private WebSocketCloseEventHandler receiver; + private WebSocketError? error; private WebSocketCloseStatus? status; - public OnDisconnectMessage(WebSocketCloseEventHandler receiver, WebSocketCloseStatus? status) + public OnDisconnectMessage(WebSocketCloseEventHandler receiver, WebSocketCloseStatus? status, + WebSocketError? error) { this.receiver = receiver; + this.error = error; this.status = status; } public override void Execute() { - receiver.Invoke(status); + receiver.Invoke(status, error); + } + } + + class OnConnectErrorMessage : MainThreadDispatch + { + private WebSocketConnectErrorEventHandler receiver; + private WebSocketError? error; + + public OnConnectErrorMessage(WebSocketConnectErrorEventHandler receiver, WebSocketError? error) + { + this.receiver = receiver; + this.error = error; + } + + public override void Execute() + { + receiver.Invoke(error); } } @@ -67,9 +87,9 @@ public override void Execute() public delegate void WebSocketMessageEventHandler(byte[] message); - public delegate void WebSocketErrorEventHandler(string errorMsg); + public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); - public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? closeCode); + public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error); public struct ConnectOptions { @@ -80,7 +100,7 @@ public struct ConnectOptions public class WebSocket { // WebSocket buffer for incoming messages - private static readonly int MAXMessageSize = 0x2000000; // 32MB + private static readonly int MAXMessageSize = 0x4000000; // 64MB // Connection parameters private readonly ConnectOptions _options; @@ -96,6 +116,7 @@ public WebSocket(ConnectOptions options) } public event WebSocketOpenEventHandler OnConnect; + public event WebSocketConnectErrorEventHandler OnConnectError; public event WebSocketMessageEventHandler OnMessage; public event WebSocketCloseEventHandler OnClose; @@ -123,18 +144,13 @@ public async Task Connect(string auth, string host, string nameOrAddress) } catch (WebSocketException ex) { - if (ex.WebSocketErrorCode == WebSocketError.UnsupportedProtocol) - { - Debug.LogError("Unsupported protocol."); - return; - } - - Debug.LogError("Error connecting: " + ex); + dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode)); return; } catch (Exception e) { - Debug.LogError("Other error: " + e); + Debug.LogException(e); + dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, null)); return; } @@ -148,47 +164,38 @@ public async Task Connect(string auth, string host, string nameOrAddress) { await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); - if (receiveResult.CloseStatus != WebSocketCloseStatus.NormalClosure) - { - Debug.LogError("Server closed connection abnormally."); - dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, receiveResult.CloseStatus)); - } + dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, receiveResult.CloseStatus, null)); + return; } - else + + var count = receiveResult.Count; + while (receiveResult.EndOfMessage == false) { - var count = receiveResult.Count; - while (receiveResult.EndOfMessage == false) + if (count >= MAXMessageSize) { - if (count >= MAXMessageSize) - { - var closeMessage = $"Maximum message size: {MAXMessageSize} bytes."; - await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, - CancellationToken.None); - return; - } - - receiveResult = await Ws.ReceiveAsync( - new ArraySegment(_receiveBuffer, count, MAXMessageSize - count), + // TODO: Improve this, we should allow clients to receive messages of whatever size + var closeMessage = $"Maximum message size: {MAXMessageSize} bytes."; + await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None); - count += receiveResult.Count; + dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, WebSocketCloseStatus.MessageTooBig, null)); + return; } - var buffCopy = new byte[count]; - for (var x = 0; x < count; x++) - buffCopy[x] = _receiveBuffer[x]; - dispatchQueue.Enqueue(new OnMessage(OnMessage, buffCopy)); + receiveResult = await Ws.ReceiveAsync( + new ArraySegment(_receiveBuffer, count, MAXMessageSize - count), + CancellationToken.None); + count += receiveResult.Count; } + + var buffCopy = new byte[count]; + for (var x = 0; x < count; x++) + buffCopy[x] = _receiveBuffer[x]; + dispatchQueue.Enqueue(new OnMessage(OnMessage, buffCopy)); } catch (WebSocketException ex) { - if (ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) - { - Debug.LogError("Server closed connection prematurely."); - dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, null)); - break; - } - - Debug.LogError(ex); + dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, null, ex.WebSocketErrorCode)); + return; } } } From 63f4550a665b1eb43ad7774dc0cf68e3ba9021dc Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Wed, 2 Nov 2022 12:09:45 +0000 Subject: [PATCH 008/223] More API updates --- .../Assets/SpacetimeDB/Scripts/NetworkManager.cs | 10 ++++------ sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 077123afcf4..1ead55682ff 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -74,13 +74,10 @@ private struct DbEvent /// public event Action onEvent; - private WebSocketDispatch.WebSocket webSocket; + private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; public static ClientCache clientDB; - private float? lastClientTick; - public static float clientTickInterval; - private Thread messageProcessThread; public static NetworkManager instance; @@ -95,16 +92,17 @@ protected void Awake() instance = this; - var options = new WebSocketDispatch.ConnectOptions + var options = new SpacetimeDB.ConnectOptions { //v1.bin.spacetimedb //v1.text.spacetimedb Protocol = "v1.bin.spacetimedb", }; - webSocket = new WebSocketDispatch.WebSocket(options); + webSocket = new SpacetimeDB.WebSocket(options); webSocket.OnMessage += OnMessageReceived; webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); webSocket.OnConnect += () => onConnect?.Invoke(); + webSocket.OnConnectError += a => onConnectError?.Invoke(a); clientDB = new ClientCache(); diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs index 4af79c9d54e..6cbac8d9ec0 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using UnityEngine; -namespace WebSocketDispatch +namespace SpacetimeDB { internal abstract class MainThreadDispatch { From a4727e6e606057cf5808f0aefc7d7a54c2971ee9 Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Wed, 2 Nov 2022 12:13:07 +0000 Subject: [PATCH 009/223] Small fix --- sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 1ead55682ff..bdaba0000a6 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -47,7 +47,7 @@ private struct DbEvent /// /// Called when a connection attempt fails. /// - public event Action onConnectError; + public event Action onConnectError; /// /// Called when a connection that was established has disconnected. From df3742f68a024fbd17e89a6ebb2ac82d8a40f2fc Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Thu, 3 Nov 2022 11:58:03 +0000 Subject: [PATCH 010/223] Improved names --- .../Assets/SpacetimeDB/Scripts/NetworkManager.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index bdaba0000a6..5491e4dfd65 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -57,12 +57,12 @@ private struct DbEvent /// /// Invoked on each row update to each table. /// - public event RowUpdate tableUpdate; + public event RowUpdate onRowUpdate; /// /// Callback is invoked after a transaction or subscription update is received and all updates have been applied. /// - public event Action onRowUpdateComplete; + public event Action onTransactionComplete; /// /// Called when we receive an identity from the server @@ -304,13 +304,13 @@ private void OnMessageProcessComplete(byte[] bytes) if (isUpdate) { // Merge delete and insert in one update - tableUpdate?.Invoke(_dbEvents[i].tableName, TableOp.Update, _dbEvents[i].oldValue, + onRowUpdate?.Invoke(_dbEvents[i].tableName, TableOp.Update, _dbEvents[i].oldValue, _dbEvents[i + 1].newValue); i++; } else { - tableUpdate?.Invoke(_dbEvents[i].tableName, _dbEvents[i].op, _dbEvents[i].oldValue, + onRowUpdate?.Invoke(_dbEvents[i].tableName, _dbEvents[i].op, _dbEvents[i].oldValue, _dbEvents[i].newValue); } } @@ -318,10 +318,10 @@ private void OnMessageProcessComplete(byte[] bytes) switch (message.TypeCase) { case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - onRowUpdateComplete?.Invoke(); + onTransactionComplete?.Invoke(); break; case ClientApi.Message.TypeOneofCase.TransactionUpdate: - onRowUpdateComplete?.Invoke(); + onTransactionComplete?.Invoke(); onEvent?.Invoke(message.TransactionUpdate.Event); break; } From e518ebe8153cda2eb38407051dc95f91a7846841 Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Thu, 3 Nov 2022 12:00:57 +0000 Subject: [PATCH 011/223] .gitignore change --- sdks/csharp/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdks/csharp/.gitignore b/sdks/csharp/.gitignore index 116e0d0723c..0da27256829 100644 --- a/sdks/csharp/.gitignore +++ b/sdks/csharp/.gitignore @@ -23,6 +23,9 @@ # Autogenerated Jetbrains Rider plugin /[Aa]ssets/Plugins/Editor/JetBrains* +# Visual Studio Code cache directory +.vscode/ + # Visual Studio cache directory .vs/ From 789b5b222342c5327578b35e9aa2fb763ae8e413 Mon Sep 17 00:00:00 2001 From: Clockwork Labs Date: Thu, 3 Nov 2022 17:17:44 +0000 Subject: [PATCH 012/223] Several fixes to sending when the websocket is closed. --- .../SpacetimeDB/Scripts/NetworkManager.cs | 8 +++- .../Assets/SpacetimeDB/Scripts/WebSocket.cs | 47 +++++++++++++++---- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 5491e4dfd65..e7597cf78d2 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -48,6 +48,11 @@ private struct DbEvent /// Called when a connection attempt fails. /// public event Action onConnectError; + + /// + /// Called when an exception occurs when sending a message. + /// + public event Action onSendError; /// /// Called when a connection that was established has disconnected. @@ -103,7 +108,8 @@ protected void Awake() webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); webSocket.OnConnect += () => onConnect?.Invoke(); webSocket.OnConnectError += a => onConnectError?.Invoke(a); - + webSocket.OnSendError += a => onSendError?.Invoke(a); + clientDB = new ClientCache(); var type = typeof(IDatabaseTable); diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs index 6cbac8d9ec0..9231b8130d3 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs @@ -65,6 +65,23 @@ public override void Execute() receiver.Invoke(error); } } + + class OnSendErrorMessage : MainThreadDispatch + { + private WebSocketSendErrorEventHandler receiver; + private Exception e; + + public OnSendErrorMessage(WebSocketSendErrorEventHandler receiver, Exception e) + { + this.receiver = receiver; + this.e = e; + } + + public override void Execute() + { + receiver.Invoke(e); + } + } class OnMessage : MainThreadDispatch { @@ -90,6 +107,7 @@ public override void Execute() public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error); + public delegate void WebSocketSendErrorEventHandler(Exception e); public struct ConnectOptions { @@ -117,6 +135,7 @@ public WebSocket(ConnectOptions options) public event WebSocketOpenEventHandler OnConnect; public event WebSocketConnectErrorEventHandler OnConnectError; + public event WebSocketSendErrorEventHandler OnSendError; public event WebSocketMessageEventHandler OnMessage; public event WebSocketCloseEventHandler OnClose; @@ -233,21 +252,29 @@ public void Send(byte[] message) private async Task ProcessSendQueue() { - while (true) + try { - byte[] message; - lock (messageSendQueue) + while (true) { - if (!messageSendQueue.TryDequeue(out message)) + byte[] message; + lock (messageSendQueue) { - // We are out of messages to send - senderTask = null; - return; + if (!messageSendQueue.TryDequeue(out message)) + { + // We are out of messages to send + senderTask = null; + return; + } } - } - await Ws!.SendAsync(new ArraySegment(message), WebSocketMessageType.Text, true, - CancellationToken.None); + await Ws!.SendAsync(new ArraySegment(message), WebSocketMessageType.Text, true, + CancellationToken.None); + } + } + catch(Exception e) + { + senderTask = null; + dispatchQueue.Enqueue(new OnSendErrorMessage(OnSendError, e)); } } From 7f4e27d4f2170aeef543f8b9fb36ffdc7ef2a0c7 Mon Sep 17 00:00:00 2001 From: Derek Brinkmann Date: Wed, 11 Jan 2023 17:11:59 -0500 Subject: [PATCH 013/223] Give SDK users access to the token key --- sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index e7597cf78d2..b2c66285047 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -87,6 +87,8 @@ private struct DbEvent public static NetworkManager instance; + public string TokenKey { get { return GetTokenKey(); } } + protected void Awake() { if (instance != null) From c499710cda5a40a384140555f49ee59bd7e0799e Mon Sep 17 00:00:00 2001 From: Derek Brinkmann Date: Fri, 13 Jan 2023 13:21:28 -0500 Subject: [PATCH 014/223] Changes to the Unity SDK to support callbacks for individual table row updates and reducer events --- .../Assets/SpacetimeDB/Scripts/ClientCache.cs | 27 ++++--- .../SpacetimeDB/Scripts/NetworkManager.cs | 72 ++++++++++++++++--- .../SpacetimeDB/Scripts/ReducerExtensions.cs | 9 +++ .../Scripts/ReducerExtensions.cs.meta | 11 +++ 4 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index bcb381b20ec..4262800243d 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -35,9 +35,10 @@ public int GetHashCode(byte[] key) } private readonly string name; - private readonly TypeDef rowSchema; - - // The function to use for decoding a type value + private readonly Type clientTableType; + private readonly TypeDef rowSchema; + + // The function to use for decoding a type value private Func decoderFunc; // Maps from primary key to type value @@ -45,9 +46,15 @@ public int GetHashCode(byte[] key) // Maps from primary key to decoded value public readonly ConcurrentDictionary decodedValues; - public TableCache(string name, TypeDef rowSchema, Func decoderFunc) + public Type ClientTableType { get => clientTableType; } + public string Name { get => name; } + public TypeDef RowSchema { get => rowSchema; } + + public TableCache(Type clientTableType, TypeDef rowSchema, Func decoderFunc) { - this.name = name; + name = clientTableType.Name; + this.clientTableType = clientTableType; + this.rowSchema = rowSchema; this.decoderFunc = decoderFunc; entries = new Dictionary(new ByteArrayComparer()); @@ -68,9 +75,7 @@ public TableCache(string name, TypeDef rowSchema, Func decode decoded = (value.Value, decoderFunc(value.Value)); decodedValues[pk] = decoded; return decoded; - } - - public TypeDef GetSchema() => rowSchema; + } /// /// Inserts the value into the table. There can be no existing value with the provided pk. @@ -127,8 +132,10 @@ public object Delete(byte[] rowPk) private readonly ConcurrentDictionary tables = new ConcurrentDictionary(); - public void AddTable(string name, TypeDef tableRowDef, Func decodeFunc) + public void AddTable(Type clientTableType, TypeDef tableRowDef, Func decodeFunc) { + string name = clientTableType.Name; + if (tables.TryGetValue(name, out _)) { Debug.LogError($"Table with name already exists: {name}"); @@ -136,7 +143,7 @@ public void AddTable(string name, TypeDef tableRowDef, Func d } // Initialize this table - tables[name] = new TableCache(name, tableRowDef, decodeFunc); + tables[name] = new TableCache(clientTableType, tableRowDef, decodeFunc); } public IEnumerable GetObjects(string name) { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index b2c66285047..d19d1f04493 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -31,7 +31,7 @@ public class Message private struct DbEvent { - public string tableName; + public Type clientTableType; public TableOp op; public object oldValue; public object newValue; @@ -82,6 +82,7 @@ private struct DbEvent private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; public static ClientCache clientDB; + public static Dictionary reducerEventCache = new Dictionary(); private Thread messageProcessThread; @@ -131,10 +132,21 @@ protected void Awake() var conversionFunc = @class.GetMethods().FirstOrDefault(a => a.Name == "op_Explicit" && a.GetParameters().Length > 0 && a.GetParameters()[0].ParameterType == typeof(TypeValue)); - clientDB.AddTable(@class.Name, typeDef, + clientDB.AddTable(@class, typeDef, a => { return conversionFunc!.Invoke(null, new object[] { a }); }); } + // cache all our reducer events by their function name + foreach (var methodInfo in (typeof(Reducer)).GetMethods()) + { + var ca = methodInfo.GetCustomAttribute(); + if (ca != null) + { + ReducerEvent reducerEvent = (ReducerEvent)ca; + reducerEventCache.Add(reducerEvent.FunctionName, methodInfo); + } + } + messageProcessThread = new Thread(ProcessMessages); messageProcessThread.Start(); } @@ -172,7 +184,7 @@ void ProcessMessages() foreach (var row in update.TableRowOperations) { var table = clientDB.GetTable(update.TableName); - var typeDef = table.GetSchema(); + var typeDef = table.RowSchema; var (typeValue, _) = TypeValue.Decode(typeDef, row.Row); if (typeValue.HasValue) { @@ -269,7 +281,7 @@ private void OnMessageProcessComplete(byte[] bytes) { _dbEvents.Add(new DbEvent { - tableName = tableName, + clientTableType = table.ClientTableType, op = TableOp.Delete, newValue = null, oldValue = deletedValue, @@ -283,7 +295,7 @@ private void OnMessageProcessComplete(byte[] bytes) { _dbEvents.Add(new DbEvent { - tableName = tableName, + clientTableType = table.ClientTableType, op = TableOp.Insert, newValue = insertedValue, oldValue = null @@ -299,28 +311,60 @@ private void OnMessageProcessComplete(byte[] bytes) var eventCount = _dbEvents.Count; for (int i = 0; i < eventCount; i++) { + string tableName = _dbEvents[i].clientTableType.Name; + bool isUpdate = false; if (i < eventCount - 1) { if (_dbEvents[i].op == TableOp.Delete && _dbEvents[i + 1].op == TableOp.Insert) { // somewhat hacky: Delete followed by an insert on the same table is considered an update. - isUpdate = _dbEvents[i].tableName.Equals(_dbEvents[i + 1].tableName); + isUpdate = tableName.Equals(_dbEvents[i + 1].clientTableType.Name); } } + TableOp tableOp = _dbEvents[i].op; + + object oldValue = _dbEvents[i].oldValue, newValue = _dbEvents[i].newValue; + if (isUpdate) { // Merge delete and insert in one update - onRowUpdate?.Invoke(_dbEvents[i].tableName, TableOp.Update, _dbEvents[i].oldValue, - _dbEvents[i + 1].newValue); + tableOp = TableOp.Update; + newValue = _dbEvents[i + 1].newValue; + i++; + + var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnUpdateEvent"); + if(clientEvent != null) + { + clientEvent.Invoke(null, new object[] { oldValue, newValue }); + } } - else + else if(tableOp == TableOp.Insert) { - onRowUpdate?.Invoke(_dbEvents[i].tableName, _dbEvents[i].op, _dbEvents[i].oldValue, - _dbEvents[i].newValue); + var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnInsertEvent"); + if (clientEvent != null) + { + clientEvent.Invoke(null, new object[] { newValue }); + } } + else if(tableOp == TableOp.Delete) + { + var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnDeleteEvent"); + if (clientEvent != null) + { + clientEvent.Invoke(null, new object[] { oldValue }); + } + } + + var clientRowUpdate = _dbEvents[i].clientTableType.GetMethod("OnRowUpdateEvent"); + if (clientRowUpdate != null) + { + clientRowUpdate.Invoke(null, new object[] { tableOp, oldValue, newValue }); + } + + onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue); } switch (message.TypeCase) @@ -331,6 +375,12 @@ private void OnMessageProcessComplete(byte[] bytes) case ClientApi.Message.TypeOneofCase.TransactionUpdate: onTransactionComplete?.Invoke(); onEvent?.Invoke(message.TransactionUpdate.Event); + + string functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; + if (reducerEventCache.ContainsKey(functionName)) + { + reducerEventCache[functionName].Invoke(null, new object[] { message.TransactionUpdate.Event }); + } break; } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs new file mode 100644 index 00000000000..12dedf74eca --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs @@ -0,0 +1,9 @@ +using System; + +namespace SpacetimeDB +{ + public class ReducerEvent : Attribute + { + public string FunctionName { get; set; } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs.meta new file mode 100644 index 00000000000..1468cea91cd --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5024d17b7a44a11458d975cb1e9913a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From ec5fa25ebd53720e11f1ba40d92117e10cd46648 Mon Sep 17 00:00:00 2001 From: Derek Brinkmann Date: Fri, 20 Jan 2023 17:26:46 -0500 Subject: [PATCH 015/223] Add sslEnabled option to Connect function --- sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs | 5 +++-- sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index b2c66285047..083b94843c4 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -202,7 +202,8 @@ private void OnDestroy() /// /// The host or IP address and the port to connect to. Example: spacetime.spacetimedb.net:3000 /// The name or address of the database to connect to - public void Connect(string host, string addressOrName) + /// Should websocket use SSL + public void Connect(string host, string addressOrName, bool sslEnabled = true) { var token = PlayerPrefs.HasKey(GetTokenKey()) ? PlayerPrefs.GetString(GetTokenKey()) : null; @@ -210,7 +211,7 @@ public void Connect(string host, string addressOrName) { try { - await webSocket.Connect(token, host, addressOrName); + await webSocket.Connect(token, host, addressOrName, sslEnabled); } catch (Exception e) { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs index 9231b8130d3..77dfe106a21 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs @@ -139,9 +139,10 @@ public WebSocket(ConnectOptions options) public event WebSocketMessageEventHandler OnMessage; public event WebSocketCloseEventHandler OnClose; - public async Task Connect(string auth, string host, string nameOrAddress) + public async Task Connect(string auth, string host, string nameOrAddress, bool sslEnabled) { - var url = new Uri($"ws://{host}/database/subscribe?name_or_address={nameOrAddress}"); + var protocol = sslEnabled ? "wss" : "ws"; + var url = new Uri($"{protocol}://{host}/database/subscribe?name_or_address={nameOrAddress}"); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000); From 2054da43fb35769b95144932055f2be84d2d3868 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Sun, 26 Feb 2023 01:38:08 -0600 Subject: [PATCH 016/223] Migrate from TypeDef/TypeValue to SATS (#5) * Fix compilation issue with master * Initial push for SATS (still WIP) * Small build fix * Small update * Updates from meeting with Tyler * Fixed issues with LayoutExplicit and added some missing functions * AlgebraicValue cleanup * Copied changes from BitCraftMini * Removed TypeDef --------- Co-authored-by: Clockwork Labs Co-authored-by: Tyler Cloutier Co-authored-by: John Detter --- .../Assets/SpacetimeDB/Scripts/ClientCache.cs | 48 +- .../Assets/SpacetimeDB/Scripts/Identity.cs | 75 +++ .../SpacetimeDB/Scripts/Identity.cs.meta | 11 + .../SpacetimeDB/Scripts/NetworkManager.cs | 135 +++-- .../Assets/SpacetimeDB/Scripts/Reducer.cs | 10 + .../SpacetimeDB/Scripts/Reducer.cs.meta | 11 + .../Assets/SpacetimeDB/Scripts/SATS.meta | 3 + .../SpacetimeDB/Scripts/SATS/AlgebraicType.cs | 185 +++++++ .../Scripts/SATS/AlgebraicType.cs.meta | 3 + .../Scripts/SATS/AlgebraicValue.cs | 368 +++++++++++++ .../Scripts/SATS/AlgebraicValue.cs.meta | 11 + .../SpacetimeDB/Scripts/SATS/Typespace.cs | 32 ++ .../Scripts/SATS/Typespace.cs.meta | 11 + .../Assets/SpacetimeDB/Scripts/TypeDef.cs | 496 ------------------ .../SpacetimeDB/Scripts/TypeDef.cs.meta | 3 - 15 files changed, 832 insertions(+), 570 deletions(-) create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index 4262800243d..a3e9492ff89 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -7,6 +7,7 @@ using Google.Protobuf; using UnityEngine; using ClientApi; +using SpacetimeDB.SATS; namespace SpacetimeDB { @@ -36,43 +37,43 @@ public int GetHashCode(byte[] key) private readonly string name; private readonly Type clientTableType; - private readonly TypeDef rowSchema; - - // The function to use for decoding a type value - private Func decoderFunc; + private readonly AlgebraicType rowSchema; + + // The function to use for decoding a type value + private Func decoderFunc; // Maps from primary key to type value - public readonly Dictionary entries; + public readonly Dictionary entries; // Maps from primary key to decoded value - public readonly ConcurrentDictionary decodedValues; + public readonly ConcurrentDictionary decodedValues; public Type ClientTableType { get => clientTableType; } public string Name { get => name; } - public TypeDef RowSchema { get => rowSchema; } + public AlgebraicType RowSchema { get => rowSchema; } - public TableCache(Type clientTableType, TypeDef rowSchema, Func decoderFunc) + public TableCache(Type clientTableType, AlgebraicType rowSchema, Func decoderFunc) { name = clientTableType.Name; this.clientTableType = clientTableType; this.rowSchema = rowSchema; this.decoderFunc = decoderFunc; - entries = new Dictionary(new ByteArrayComparer()); - decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); + entries = new Dictionary(new ByteArrayComparer()); + decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); } - public (TypeValue?, object) Decode(byte[] pk, TypeValue? value) + public (AlgebraicValue, object) Decode(byte[] pk, AlgebraicValue value) { if (decodedValues.TryGetValue(pk, out var decoded)) { return decoded; } - if (!value.HasValue) + if (value == null) { return (null, null); } - decoded = (value.Value, decoderFunc(value.Value)); + decoded = (value, decoderFunc(value)); decodedValues[pk] = decoded; return decoded; } @@ -89,9 +90,9 @@ public object Insert(byte[] rowPk) } var decodedTuple = Decode(rowPk, null); - if (decodedTuple.Item1.HasValue && decodedTuple.Item2 != null) + if (decodedTuple.Item1 != null && decodedTuple.Item2 != null) { - entries[rowPk] = (decodedTuple.Item1.Value, decodedTuple.Item2); + entries[rowPk] = (decodedTuple.Item1, decodedTuple.Item2); return decodedTuple.Item2; } @@ -132,7 +133,7 @@ public object Delete(byte[] rowPk) private readonly ConcurrentDictionary tables = new ConcurrentDictionary(); - public void AddTable(Type clientTableType, TypeDef tableRowDef, Func decodeFunc) + public void AddTable(Type clientTableType, AlgebraicType tableRowDef, Func decodeFunc) { string name = clientTableType.Name; @@ -158,7 +159,7 @@ public IEnumerable GetObjects(string name) } } - public IEnumerable GetEntries(string name) + public IEnumerable GetEntries(string name) { if (!tables.TryGetValue(name, out var table)) { @@ -181,5 +182,16 @@ public TableCache GetTable(string name) Debug.LogError($"We don't know that this table is: {name}"); return null; } + + public int Count(string name) + { + if (!tables.TryGetValue(name, out var table)) + { + return 0; + } + return table.entries.Count; + } + + public IEnumerable GetTableNames() => tables.Keys; } -} \ No newline at end of file +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs new file mode 100644 index 00000000000..9dcef88b09c --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using SpacetimeDB.SATS; +using UnityEngine; + +namespace SpacetimeDB +{ + public struct Identity : IEquatable + { + private byte[] bytes; + + public static int SIZE = 32; + + public byte[] Bytes => bytes; + + public static AlgebraicType GetAlgebraicType() + { + return new AlgebraicType + { + type = AlgebraicType.Type.Builtin, + builtin = new BuiltinType + { + type = BuiltinType.Type.Array, + arrayType = new AlgebraicType + { + type = AlgebraicType.Type.Builtin, + builtin = new BuiltinType + { + type = BuiltinType.Type.U8 + } + } + } + }; + } + + public static explicit operator Identity(AlgebraicValue v) => new Identity + { + bytes = v.AsBytes(), + }; + + public static Identity From(byte[] bytes) + { + // TODO: should we validate length here? + return new Identity + { + bytes = bytes, + }; + } + + public bool Equals(Identity other) + { + return bytes.SequenceEqual(other.bytes); + } + + public override bool Equals(object o) + { + return o is Identity other && Equals(other); + } + + public static bool operator ==(Identity a, Identity b) => a.Equals(b); + public static bool operator !=(Identity a, Identity b) => !a.Equals(b); + + public override int GetHashCode() + { + if (bytes == null) + { + throw new InvalidOperationException("Cannot hash on null bytes."); + } + + return bytes.GetHashCode(); + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs.meta new file mode 100644 index 00000000000..9ece25fbd72 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 924c91782f80dffba9114a596343ef14 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 55c5017953c..f517752a106 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -1,14 +1,18 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net.WebSockets; using System.Reflection; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using ClientApi; +using Newtonsoft.Json; using SpacetimeDB; +using SpacetimeDB.SATS; using UnityEngine; namespace SpacetimeDB @@ -22,13 +26,17 @@ public enum TableOp Update } - [Serializable] - public class Message + public class ReducerCallRequest { public string fn; public object[] args; } + public class SubscriptionRequest + { + public string subscriptionQuery; + } + private struct DbEvent { public Type clientTableType; @@ -48,7 +56,7 @@ private struct DbEvent /// Called when a connection attempt fails. /// public event Action onConnectError; - + /// /// Called when an exception occurs when sending a message. /// @@ -72,7 +80,7 @@ private struct DbEvent /// /// Called when we receive an identity from the server /// - public event Action onIdentityReceived; + public event Action onIdentityReceived; /// /// Invoked when an event message is received or at the end of a transaction update. @@ -88,7 +96,10 @@ private struct DbEvent public static NetworkManager instance; - public string TokenKey { get { return GetTokenKey(); } } + public string TokenKey + { + get { return GetTokenKey(); } + } protected void Awake() { @@ -112,7 +123,7 @@ protected void Awake() webSocket.OnConnect += () => onConnect?.Invoke(); webSocket.OnConnectError += a => onConnectError?.Invoke(a); webSocket.OnSendError += a => onSendError?.Invoke(a); - + clientDB = new ClientCache(); var type = typeof(IDatabaseTable); @@ -126,27 +137,24 @@ protected void Awake() continue; } - var typeDefFunc = @class.GetMethod("GetTypeDef", BindingFlags.Static | BindingFlags.Public); - var typeDef = typeDefFunc!.Invoke(null, null) as TypeDef; - // var conversionFunc = @class.GetMethod("op_Explicit"); + var algebraicTypeFunc = @class.GetMethod("GetAlgebraicType", BindingFlags.Static | BindingFlags.Public); + var algebraicValue = algebraicTypeFunc!.Invoke(null, null) as AlgebraicType; var conversionFunc = @class.GetMethods().FirstOrDefault(a => a.Name == "op_Explicit" && a.GetParameters().Length > 0 && - a.GetParameters()[0].ParameterType == typeof(TypeValue)); - clientDB.AddTable(@class, typeDef, + a.GetParameters()[0].ParameterType == typeof(AlgebraicValue)); + clientDB.AddTable(@class, algebraicValue, a => { return conversionFunc!.Invoke(null, new object[] { a }); }); } // cache all our reducer events by their function name - foreach (var methodInfo in (typeof(Reducer)).GetMethods()) - { - var ca = methodInfo.GetCustomAttribute(); - if (ca != null) - { - ReducerEvent reducerEvent = (ReducerEvent)ca; - reducerEventCache.Add(reducerEvent.FunctionName, methodInfo); - } + foreach (var methodInfo in typeof(SpacetimeDB.Reducer).GetMethods()) + { + if (methodInfo.GetCustomAttribute() is { } reducerEvent) + { + reducerEventCache.Add(reducerEvent.FunctionName, methodInfo); + } } - + messageProcessThread = new Thread(ProcessMessages); messageProcessThread.Start(); } @@ -176,25 +184,32 @@ void ProcessMessages() { case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: case ClientApi.Message.TypeOneofCase.TransactionUpdate: + { // First apply all of the state System.Diagnostics.Debug.Assert(subscriptionUpdate != null, nameof(subscriptionUpdate) + " != null"); + using var stream = new MemoryStream(); + using var reader = new BinaryReader(stream); foreach (var update in subscriptionUpdate.TableUpdates) { foreach (var row in update.TableRowOperations) { + stream.Position = 0; + stream.SetLength(row.Row.Length); + stream.Write(row.Row.ToByteArray(), 0, row.Row.Length); + stream.Position = 0; var table = clientDB.GetTable(update.TableName); - var typeDef = table.RowSchema; - var (typeValue, _) = TypeValue.Decode(typeDef, row.Row); - if (typeValue.HasValue) + var algebraicType = table.RowSchema; + var algebraicValue = AlgebraicValue.Deserialize(algebraicType, reader); + if (algebraicValue != null) { // Here we are decoding on our message thread so that by the time we get to the // main thread the cache is already warm. - table.Decode(row.RowPk.ToByteArray(), typeValue.Value); + table.Decode(row.RowPk.ToByteArray(), algebraicValue); } } } - + } break; } @@ -332,37 +347,37 @@ private void OnMessageProcessComplete(byte[] bytes) { // Merge delete and insert in one update tableOp = TableOp.Update; - newValue = _dbEvents[i + 1].newValue; - + newValue = _dbEvents[i + 1].newValue; + i++; var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnUpdateEvent"); - if(clientEvent != null) - { - clientEvent.Invoke(null, new object[] { oldValue, newValue }); - } + if (clientEvent != null) + { + clientEvent.Invoke(null, new object[] { oldValue, newValue }); + } } - else if(tableOp == TableOp.Insert) + else if (tableOp == TableOp.Insert) { var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnInsertEvent"); - if (clientEvent != null) - { - clientEvent.Invoke(null, new object[] { newValue }); + if (clientEvent != null) + { + clientEvent.Invoke(null, new object[] { newValue }); } } - else if(tableOp == TableOp.Delete) - { + else if (tableOp == TableOp.Delete) + { var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnDeleteEvent"); - if (clientEvent != null) - { - clientEvent.Invoke(null, new object[] { oldValue }); - } + if (clientEvent != null) + { + clientEvent.Invoke(null, new object[] { oldValue }); + } } - var clientRowUpdate = _dbEvents[i].clientTableType.GetMethod("OnRowUpdateEvent"); - if (clientRowUpdate != null) - { - clientRowUpdate.Invoke(null, new object[] { tableOp, oldValue, newValue }); + var clientRowUpdate = _dbEvents[i].clientTableType.GetMethod("OnRowUpdateEvent"); + if (clientRowUpdate != null) + { + clientRowUpdate.Invoke(null, new object[] { tableOp, oldValue, newValue }); } onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue); @@ -377,17 +392,19 @@ private void OnMessageProcessComplete(byte[] bytes) onTransactionComplete?.Invoke(); onEvent?.Invoke(message.TransactionUpdate.Event); - string functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; - if (reducerEventCache.ContainsKey(functionName)) - { - reducerEventCache[functionName].Invoke(null, new object[] { message.TransactionUpdate.Event }); + var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; + if (reducerEventCache.ContainsKey(functionName)) + { + reducerEventCache[functionName] + .Invoke(null, new object[] { message.TransactionUpdate.Event }); } + break; } break; case ClientApi.Message.TypeOneofCase.IdentityToken: - onIdentityReceived?.Invoke(Hash.From(message.IdentityToken.Identity.ToByteArray())); + onIdentityReceived?.Invoke(Identity.From(message.IdentityToken.Identity.ToByteArray())); PlayerPrefs.SetString(GetTokenKey(), message.IdentityToken.Token); break; case ClientApi.Message.TypeOneofCase.Event: @@ -409,10 +426,22 @@ private string GetTokenKey() return key; } - internal void InternalCallReducer(Message message) + internal void InternalCallReducer(string reducer, object[] args) + { + // var argBytes = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(args)); + var message = new ReducerCallRequest + { + fn = reducer, + args = args, + }; + var json = JsonConvert.SerializeObject(message); + webSocket.Send(Encoding.ASCII.GetBytes("{ \"call\": " + json + " }")); + } + + public void Subscribe(List queries) { - var json = Newtonsoft.Json.JsonConvert.SerializeObject(message); - webSocket.Send(Encoding.ASCII.GetBytes(json)); + var json = JsonConvert.SerializeObject(queries); + webSocket.Send(Encoding.ASCII.GetBytes("{ \"subscribe\": { \"query_strings\": " + json + " }}")); } private void Update() diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs new file mode 100644 index 00000000000..9bc7d99a10b --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs @@ -0,0 +1,10 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SpacetimeDB +{ + public partial class Reducer + { + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs.meta new file mode 100644 index 00000000000..7f8d4251241 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c5f8f3b1a67eaf268e00840da8aa4bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS.meta new file mode 100644 index 00000000000..e863bcf9152 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c8d7d4943ee54be3abeac55aa74718e6 +timeCreated: 1677030685 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs new file mode 100644 index 00000000000..76c177b2dae --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs @@ -0,0 +1,185 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Runtime.InteropServices; + +namespace SpacetimeDB.SATS +{ + public class SumType + { + public List variants; + + public SumType() + { + variants = new List(); + } + + // TODO(jdetter): Perhaps not needed? + public SumType NewUnnamed() + { + var s = new SumType + { + variants = variants.Select(a => new SumTypeVariant(null, a.algebraicType)).ToList() + }; + return s; + } + } + + public struct SumTypeVariant + { + public string name; + public AlgebraicType algebraicType; + + public SumTypeVariant(string name, AlgebraicType algebraicType) + { + this.name = name; + this.algebraicType = algebraicType; + } + } + + public class ProductType + { + public List elements; + + public ProductType() + { + elements = new List(); + } + } + + public struct ProductTypeElement + { + public string name; + public AlgebraicType algebraicType; + + public ProductTypeElement(string name, AlgebraicType algebraicType) + { + this.name = name; + this.algebraicType = algebraicType; + } + + public ProductTypeElement(AlgebraicType algebraicType) + { + name = null; + this.algebraicType = algebraicType; + } + } + + public struct MapType + { + public AlgebraicType keyType; + public AlgebraicType valueType; + } + + public class BuiltinType + { + public enum Type + { + Bool, + I8, + U8, + I16, + U16, + I32, + U32, + I64, + U64, + I128, + U128, + F32, + F64, + String, + Array, + Map + } + + public Type type; + + public AlgebraicType arrayType; + public MapType mapType; + } + + public class AlgebraicType + { + public enum Type + { + Sum, + Product, + Builtin, + TypeRef, + None, + } + + public Type type; + private object type_; + + public SumType sum { + get { return type == Type.Sum ? (SumType)type_ : null; } + set { + type_ = value; + type = value == null ? Type.None : Type.Sum; + } + } + + public ProductType product { + get { return type == Type.Product ? (ProductType)type_ : null; } + set { + type_ = value; + type = value == null ? Type.None : Type.Product; + } + } + + public BuiltinType builtin { + get { return type == Type.Builtin ? (BuiltinType)type_ : null; } + set { + type_ = value; + type = value == null ? Type.None : Type.Builtin; + } + } + + public int typeRef { + get { return type == Type.TypeRef ? (int)type_ : -1; } + set { + type_ = value; + type = value == -1 ? Type.None : Type.TypeRef; + } + } + + public static AlgebraicType CreateProductType(IEnumerable elements) + { + return new AlgebraicType + { + type = Type.Product, + product = new ProductType + { + elements = elements.ToList() + } + }; + } + + public static AlgebraicType CreateArrayType(AlgebraicType elementType) { + return new AlgebraicType + { + type = Type.Builtin, + builtin = new BuiltinType + { + type = BuiltinType.Type.Array, + arrayType = elementType + } + }; + } + + public static AlgebraicType CreatePrimitiveType(BuiltinType.Type type) { + return new AlgebraicType + { + type = Type.Builtin, + builtin = new BuiltinType + { + type = type, + } + }; + } + + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs.meta new file mode 100644 index 00000000000..5c2a0f8e14b --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2aa159e7cb07436a9997df464c908be2 +timeCreated: 1677030697 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs new file mode 100644 index 00000000000..579ba0dca96 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs @@ -0,0 +1,368 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using Google.Protobuf.WellKnownTypes; +using TMPro; +using UnityEditor.Build.Content; +using UnityEngine; +using Type = System.Type; + +namespace SpacetimeDB.SATS +{ + public struct BuiltinValue + { + private object value; + + public bool AsBool() => (bool)value; + public sbyte AsI8() => (sbyte)value; + public byte AsU8() => (byte)value; + public short AsI16() => (short)value; + public ushort AsU16() => (ushort)value; + public int AsI32() => (int)value; + public uint AsU32() => (uint)value; + public long AsI64() => (long)value; + public ulong AsU64() => (ulong)value; + public byte[] AsI128() => (byte[])value; + public byte[] AsU128() => (byte[])value; + public float AsF32() => (float)value; + public double AsF64() => (double)value; + public byte[] AsBytes() => (byte[])value; + public string AsString() => (string)value; + public List AsArray() => (List)value; + public Dictionary AsMap() => (Dictionary)value; + + public static BuiltinValue CreateBool(bool value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateI8(sbyte value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateU8(byte value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateI16(short value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateU16(ushort value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateI32(int value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateU32(uint value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateI64(long value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateU64(ulong value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateI128(byte[] value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateU128(byte[] value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateF32(float value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateF64(double value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateString(string value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateBytes(byte[] value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateArray(List value) => new BuiltinValue { value = value }; + public static BuiltinValue CreateMap(Dictionary value) => new BuiltinValue { value = value }; + + public void Serialize(BuiltinType type, BinaryWriter writer) + { + void WriteByteBuffer(byte[] buf) + { + if (buf.LongLength > uint.MaxValue) + { + throw new Exception("Serializing a buffer that is too large for SATS."); + } + + writer.Write((uint)buf.LongLength); + writer.Write(buf); + } + + switch (type.type) + { + case BuiltinType.Type.Bool: + writer.Write(AsBool()); + break; + case BuiltinType.Type.I8: + writer.Write(AsI8()); + break; + case BuiltinType.Type.U8: + writer.Write(AsU8()); + break; + case BuiltinType.Type.I16: + writer.Write(AsI16()); + break; + case BuiltinType.Type.U16: + writer.Write(AsU16()); + break; + case BuiltinType.Type.I32: + writer.Write(AsI32()); + break; + case BuiltinType.Type.U32: + writer.Write(AsU32()); + break; + case BuiltinType.Type.I64: + writer.Write(AsI64()); + break; + case BuiltinType.Type.U64: + writer.Write(AsU64()); + break; + case BuiltinType.Type.I128: + writer.Write(AsI128()); + break; + case BuiltinType.Type.U128: + writer.Write(AsU128()); + break; + case BuiltinType.Type.F32: + writer.Write(AsF32()); + break; + case BuiltinType.Type.F64: + writer.Write(AsF64()); + break; + case BuiltinType.Type.String: + WriteByteBuffer(System.Text.Encoding.UTF8.GetBytes((string)value)); + break; + case BuiltinType.Type.Array: + if (type.arrayType.type == AlgebraicType.Type.Builtin && + type.arrayType.builtin.type == BuiltinType.Type.U8) + { + WriteByteBuffer(AsBytes()); + break; + } + + var array = AsArray(); + writer.Write(array.Count); + foreach (var entry in array) + { + entry.Serialize(type.arrayType, writer); + } + break; + case BuiltinType.Type.Map: + throw new NotImplementedException(); + } + } + + public static BuiltinValue Deserialize(BuiltinType type, BinaryReader reader) + { + byte[] ReadByteArray() + { + var len = reader.ReadUInt32(); + if (len > int.MaxValue) + { + var arrays = new List(); + long read = 0; + while (read < len) + { + var remaining = len - read; + var readResult = reader.ReadBytes(remaining > int.MaxValue ? int.MaxValue : (int)remaining); + arrays.Add(readResult); + read += readResult.Length; + } + + var result = new byte[len]; + long pos = 0; + foreach (var array in arrays) + { + Array.Copy(array, 0, result, pos, array.LongLength); + pos += array.LongLength; + } + + return result; + } + + return reader.ReadBytes((int)len); + } + + switch (type.type) + { + case BuiltinType.Type.Bool: + return CreateBool(reader.ReadByte() != 0); + case BuiltinType.Type.I8: + return CreateI8(reader.ReadSByte()); + case BuiltinType.Type.U8: + return CreateU8(reader.ReadByte()); + case BuiltinType.Type.I16: + return CreateI16(reader.ReadInt16()); + case BuiltinType.Type.U16: + return CreateU16(reader.ReadUInt16()); + case BuiltinType.Type.I32: + return CreateI32(reader.ReadInt32()); + case BuiltinType.Type.U32: + return CreateU32(reader.ReadUInt32()); + case BuiltinType.Type.I64: + return CreateI64(reader.ReadInt64()); + case BuiltinType.Type.U64: + return CreateU64(reader.ReadUInt64()); + case BuiltinType.Type.I128: + return CreateI128(reader.ReadBytes(16)); + case BuiltinType.Type.U128: + return CreateU128(reader.ReadBytes(16)); + case BuiltinType.Type.F32: + return CreateF32(reader.ReadSingle()); + case BuiltinType.Type.F64: + return CreateF64(reader.ReadDouble()); + case BuiltinType.Type.String: + return CreateString(System.Text.Encoding.UTF8.GetString(ReadByteArray())); + case BuiltinType.Type.Array: + if (type.arrayType.type == AlgebraicType.Type.Builtin && + type.arrayType.builtin.type == BuiltinType.Type.U8) + { + return CreateBytes(ReadByteArray()); + } + + var length = reader.ReadInt32(); + var arrayResult = new List(); + for (var x = 0; x < length; x++) + { + arrayResult.Add(AlgebraicValue.Deserialize(type.arrayType, reader)); + } + + return CreateArray(arrayResult); + case BuiltinType.Type.Map: + { + var len = reader.ReadUInt32(); + var mapResult = new Dictionary(); + for (var x = 0; x < len; x++) + { + var key = AlgebraicValue.Deserialize(type.mapType.keyType, reader); + var value = AlgebraicValue.Deserialize(type.mapType.valueType, reader); + mapResult.Add(key, value); + } + + return CreateMap(mapResult); + } + default: + throw new NotImplementedException(); + } + } + } + + public class SumValue + { + public byte tag; + public AlgebraicValue value; + + private SumValue() + { + } + + public SumValue(byte tag, AlgebraicValue value) + { + this.tag = tag; + this.value = value; + } + + public static SumValue Deserialize(SumType type, BinaryReader reader) + { + var result = new SumValue(); + result.tag = reader.ReadByte(); + result.value = AlgebraicValue.Deserialize(type.variants[result.tag].algebraicType, reader); + return result; + } + + public void Serialize(SumType type, BinaryWriter writer) + { + writer.Write(tag); + value.Serialize(type.variants[tag].algebraicType, writer); + } + } + + public class ProductValue + { + public List elements; + + public ProductValue() + { + elements = new List(); + } + + public void Serialize(ProductType type, BinaryWriter writer) + { + writer.Write((uint)elements.Count); + for (var x = 0; x < elements.Count; x++) + { + elements[x].Serialize(type.elements[x].algebraicType, writer); + } + } + + public static ProductValue Deserialize(ProductType type, BinaryReader reader) + { + var result = new ProductValue(); + for (var x = 0; x < type.elements.Count; x++) + { + result.elements.Add(AlgebraicValue.Deserialize(type.elements[x].algebraicType, reader)); + } + + return result; + } + } + + public class AlgebraicValue + { + public SumValue sum; + public ProductValue product; + public BuiltinValue builtin; + + public bool AsBool() => builtin.AsBool(); + public sbyte AsI8() => builtin.AsI8(); + public byte AsU8() => builtin.AsU8(); + public short AsI16() => builtin.AsI16(); + public ushort AsU16() => builtin.AsU16(); + public int AsI32() => builtin.AsI32(); + public uint AsU32() => builtin.AsU32(); + public long AsI64() => builtin.AsI64(); + public ulong AsU64() => builtin.AsU64(); + public byte[] AsI128() => builtin.AsI128(); + public byte[] AsU128() => builtin.AsU128(); + public float AsF32() => builtin.AsF32(); + public double AsF64() => builtin.AsF64(); + public string AsString() => builtin.AsString(); + public byte[] AsBytes() => builtin.AsBytes(); + public List AsArray() => builtin.AsArray(); + public Dictionary AsMap() => builtin.AsMap(); + public static AlgebraicValue CreateBool(bool v) => new AlgebraicValue { builtin = BuiltinValue.CreateBool(v) }; + public static AlgebraicValue CreateI8(sbyte v) => new AlgebraicValue { builtin = BuiltinValue.CreateI8(v) }; + public static AlgebraicValue CreateU8(byte v) => new AlgebraicValue { builtin = BuiltinValue.CreateU8(v) }; + public static AlgebraicValue CreateI16(short v) => new AlgebraicValue { builtin = BuiltinValue.CreateI16(v) }; + public static AlgebraicValue CreateU16(ushort v) => new AlgebraicValue { builtin = BuiltinValue.CreateU16(v) }; + public static AlgebraicValue CreateI32(int v) => new AlgebraicValue { builtin = BuiltinValue.CreateI32(v) }; + public static AlgebraicValue CreateU32(uint v) => new AlgebraicValue { builtin = BuiltinValue.CreateU32(v) }; + public static AlgebraicValue CreateI64(long v) => new AlgebraicValue { builtin = BuiltinValue.CreateI64(v) }; + public static AlgebraicValue CreateU64(ulong v) => new AlgebraicValue { builtin = BuiltinValue.CreateU64(v) }; + public static AlgebraicValue CreateI128(byte[] v) => new AlgebraicValue { builtin = BuiltinValue.CreateI128(v) }; + public static AlgebraicValue CreateU128(byte[] v) => new AlgebraicValue { builtin = BuiltinValue.CreateU128(v) }; + public static AlgebraicValue CreateF32(float v) => new AlgebraicValue { builtin = BuiltinValue.CreateF32(v) }; + public static AlgebraicValue CreateF64(double v) => new AlgebraicValue { builtin = BuiltinValue.CreateF64(v) }; + public static AlgebraicValue CreateString(string v) => new AlgebraicValue { builtin = BuiltinValue.CreateString(v) }; + public static AlgebraicValue CreateBytes(byte[] v) => new AlgebraicValue { builtin = BuiltinValue.CreateBytes(v) }; + public static AlgebraicValue CreateArray(List v) => new AlgebraicValue { builtin = BuiltinValue.CreateArray(v) }; + public static AlgebraicValue CreateMap(Dictionary v) => new AlgebraicValue { builtin = BuiltinValue.CreateMap(v) }; + + public BuiltinValue AsBuiltInValue() => builtin; + public ProductValue AsProductValue() => product; + public SumValue AsSumValue() => sum; + + public static AlgebraicValue Create(BuiltinValue value) => new AlgebraicValue { builtin = value }; + public static AlgebraicValue Create(ProductValue value) => new AlgebraicValue { product = value }; + public static AlgebraicValue Create(SumValue value) => new AlgebraicValue { sum = value }; + + public static AlgebraicValue Deserialize(AlgebraicType type, BinaryReader reader) + { + switch (type.type) + { + case AlgebraicType.Type.Builtin: + return Create(BuiltinValue.Deserialize(type.builtin, reader)); + case AlgebraicType.Type.Product: + return Create(ProductValue.Deserialize(type.product, reader)); + case AlgebraicType.Type.Sum: + return Create(SumValue.Deserialize(type.sum, reader)); + default: + throw new NotImplementedException(); + } + } + + public void Serialize(AlgebraicType type, BinaryWriter writer) + { + switch (type.type) + { + case AlgebraicType.Type.Builtin: + builtin.Serialize(type.builtin, writer); + break; + case AlgebraicType.Type.Product: + product.Serialize(type.product, writer); + break; + case AlgebraicType.Type.Sum: + sum.Serialize(type.sum, writer); + break; + default: + throw new NotImplementedException(); + } + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs.meta new file mode 100644 index 00000000000..e80a032b531 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e726bf2bab07b0fca9c5affebb1dd39d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs new file mode 100644 index 00000000000..307e16a5e1b --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs @@ -0,0 +1,32 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace SpacetimeDB.SATS +{ + public class Typespace + { + public int rootRef; + public List types; + + public Typespace() + { + rootRef = 0; + types = new List(); + } + + public void Add(AlgebraicType type) + { + types.Add(type); + } + + public AlgebraicType GetRoot() => types[rootRef]; + } + + public struct GenCtx + { + public Typespace typespace; + public List names; + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs.meta new file mode 100644 index 00000000000..18b3c1e5e30 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c25f637015fec0d56843e6450fb0216f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs deleted file mode 100644 index 1883e3ad26f..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs +++ /dev/null @@ -1,496 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Google.Protobuf; -using UnityEngine; - -namespace SpacetimeDB -{ - public class TypeDef - { - public enum Def - { - Tuple = 0, - Enum, - - // base types - Vec, - U8, - U16, - U32, - U64, - U128, - I8, - I16, - I32, - I64, - I128, - Bool, - F32, - F64, - String, - Bytes, - Hash, - Unit, - } - - public Def Type => type; - public ElementDef[] TupleElements => tupleElements; - - public TypeDef VecMemberType => vecMemberType; - - public Def type; - private TypeDef vecMemberType; - public ElementDef[] tupleElements; - - public static TypeDef GetVec(TypeDef memberType) - { - return new TypeDef - { - type = Def.Vec, - vecMemberType = memberType, - }; - } - - public static TypeDef BuiltInType(Def def) - { - switch (def) - { - case Def.Tuple: - case Def.Enum: - case Def.Vec: - Debug.LogError("This is not a built-in type"); - break; - } - - return new TypeDef - { - type = def, - }; - } - - public static TypeDef Tuple(ElementDef[] elements) - { - return new TypeDef - { - type = Def.Tuple, - tupleElements = elements, - }; - } - } - - public struct ElementDef - { - public byte tag; - public TypeDef element; - - public ElementDef(byte tag, TypeDef element) - { - this.tag = tag; - this.element = element; - } - } - - public struct TypeValue - { - public class TypeValueComparer : IEqualityComparer - { - public bool Equals(TypeValue value1, TypeValue value2) - { - if (value1.typeDef.Type != value2.typeDef.Type) - { - return false; - } - - // Handle any strange cases - switch (value1.typeDef.Type) - { - case TypeDef.Def.Tuple: - if ((value1.tupleElements == null) != (value2.tupleElements == null)) - { - return false; - } - - if (value1.tupleElements == null) - { - break; - } - - if (value1.tupleElements.Length != value2.tupleElements.Length) - { - return false; - } - - break; - } - - return true; - } - - public int GetHashCode(TypeValue obj) - { - switch (obj.typeDef.Type) - { - case TypeDef.Def.Bool: - return (int)(obj.b ? 0xab745abf : 0xf60d5833); - case TypeDef.Def.Bytes: - if (obj.bytes == null) - { - throw new InvalidOperationException("Cannot hash on null bytes."); - } - - return (int)(obj.bytes.GetHashCode() ^ 0x8595a70b); - case TypeDef.Def.Enum: - throw new NotImplementedException(); - case TypeDef.Def.F32: - case TypeDef.Def.F64: - throw new InvalidOperationException("Cannot hash on floats"); - case TypeDef.Def.Hash: - return (int)(obj.hash.GetHashCode() ^ 0x8595a70b); - case TypeDef.Def.I8: - return (int)(obj.signed ^ 0x6bac6c4e); - case TypeDef.Def.I16: - return (int)(obj.signed ^ 0x2b4e01bf); - case TypeDef.Def.I32: - return (int)(obj.signed ^ 0xe32a7812); - case TypeDef.Def.I64: - return (int)(obj.signed ^ 0xab745abf ^ (obj.signed >> 32)); - case TypeDef.Def.U8: - return (int)(obj.unsigned ^ 0xc2964a29); - case TypeDef.Def.U16: - return (int)(obj.unsigned ^ 0xfb504320); - case TypeDef.Def.U32: - return (int)(obj.unsigned ^ 0x74208545); - case TypeDef.Def.U64: - return (int)(obj.unsigned ^ 0x3ef90ce5 ^ (obj.unsigned >> 32)); - case TypeDef.Def.I128: - case TypeDef.Def.U128: - throw new InvalidOperationException("Hashing on 128 bit integers unsupported"); - case TypeDef.Def.String: - if (obj.str == null) - { - throw new InvalidOperationException("Cannot hash on null string."); - } - - return obj.str.GetHashCode() ^ 0x33e1b1f4; - case TypeDef.Def.Tuple: - { - var hash = (int)(obj.tupleElements.Length ^ 0xbbce67bf); - foreach (var element in obj.tupleElements) - { - hash ^= element.GetHashCode(); - } - - return hash; - } - case TypeDef.Def.Unit: - return 0x64b22bc4; - case TypeDef.Def.Vec: - var vecHash = 0x0fec85d5; - foreach (var value in obj.vec) - { - vecHash ^= value.GetHashCode(); - } - - return vecHash; - } - - throw new NotImplementedException($"Hashing on: {obj.typeDef.Type}"); - } - } - - public TypeDef TypeDef => typeDef; - - private TypeDef typeDef; - private ulong unsigned; - private long signed; - private string str; - private byte[] bytes; - private Hash hash; - private bool b; - - private float f32; - private double f64; - private TypeValue[] tupleElements; - private List vec; - - public override string ToString() - { - if (tupleElements != null) { - var s = "(\n"; - foreach (var e in tupleElements) { - s += "\t"; - s += e.ToString(); - s += "\n"; - } - s += ")"; - return s; - } else { - return String.Format($"typeDef={typeDef.Type}, unsigned={unsigned}, signed={signed}, str={str}, bytes={bytes}, bool={b}, float={f32}, double={f64}"); - } - } - - internal static (TypeValue?, int) Decode(TypeDef def, ByteString bytes) - { - var b = bytes[1]; - var byteArr = bytes.ToByteArray(); - return Decode(def, byteArr, 0, byteArr.Length); - } - - internal static (TypeValue?, int) Decode(TypeDef def, byte[] arr, int offset, int length) - { - var value = new TypeValue - { - typeDef = def - }; - var read = 0; - - try - { - switch (def.Type) - { - case TypeDef.Def.Bool: - value.b = arr[offset] != 0; - read = 1; - break; - case TypeDef.Def.U8: - value.unsigned = arr[offset]; - read = 1; - break; - case TypeDef.Def.U16: - value.unsigned = BitConverter.ToUInt16(arr, offset); - read = 2; - break; - case TypeDef.Def.U32: - value.unsigned = BitConverter.ToUInt32(arr, offset); - read = 4; - break; - case TypeDef.Def.U64: - value.unsigned = BitConverter.ToUInt64(arr, offset); - read = 8; - break; - case TypeDef.Def.I8: - value.signed = arr[offset]; - read = 1; - break; - case TypeDef.Def.I16: - value.signed = BitConverter.ToInt16(arr, offset); - read = 2; - break; - case TypeDef.Def.I32: - value.signed = BitConverter.ToInt32(arr, offset); - read = 4; - break; - case TypeDef.Def.I64: - value.signed = BitConverter.ToInt64(arr, offset); - read = 8; - break; - case TypeDef.Def.F32: - value.f32 = BitConverter.ToSingle(arr, offset); - read = 4; - break; - case TypeDef.Def.F64: - value.f64 = BitConverter.ToDouble(arr, offset); - read = 8; - break; - case TypeDef.Def.String: - var strLength = BitConverter.ToUInt16(arr, offset); - value.str = Encoding.UTF8.GetString(arr, offset + 2, strLength); - read += strLength + 2; - break; - case TypeDef.Def.Bytes: - var byteLength = BitConverter.ToUInt16(arr, offset); - if (byteLength >= arr.Length - (offset + 2)) - { - throw new InvalidOperationException( - $"Read error: byte array goes past the end of the array: {byteLength}"); - } - - value.bytes = new byte[byteLength]; - Array.Copy(arr, offset + 2, value.bytes, 0, byteLength); - read += byteLength + 2; - break; - case TypeDef.Def.Hash: - byte[] hashVal = new byte[Hash.SIZE]; - Array.Copy(arr, offset, hashVal, 0, Hash.SIZE); - read += Hash.SIZE; - value.hash = Hash.From(hashVal); - break; - case TypeDef.Def.Tuple: - return ReadTuple(def, arr, offset, length); - case TypeDef.Def.Vec: - if (def.VecMemberType == null) - { - throw new InvalidOperationException("Read error: vec has no member type!"); - } - - var vecLength = BitConverter.ToUInt16(arr, offset); - read += 2; - value.vec = new List(); - for (var idx = 0; idx < vecLength; idx++) - { - var (entry, subDecodeRead) = Decode(def.VecMemberType, arr, offset + read, length); - read += subDecodeRead; - if (entry.HasValue) - { - value.vec.Add(entry.Value); - } - } - - break; - default: - Debug.LogError($"This type is unsupported for now: {def.Type}"); - return (null, 0); - } - } - catch (Exception e) - { - Debug.LogException(e); - Debug.LogError("Please report this error in the SpacetimeDB discord."); - return (null, 0); - } - - return (value, read); - } - - private static (TypeValue?, int) ReadTuple(TypeDef def, byte[] arr, int offset, int length) - { - var read = 0; - var resultElements = new TypeValue[def.TupleElements.Length]; - var elementIdx = 0; - foreach (var elementDef in def.TupleElements) - { - var (value, bytesRead) = Decode(elementDef.element, arr, offset + read, length); - - if (!value.HasValue) - { - return (null, 0); - } - - read += bytesRead; - resultElements[elementIdx++] = value.Value; - } - - return (GetTuple(def, resultElements), read); - } - - public object GetValue(TypeDef.Def def) - { - switch (def) - { - case TypeDef.Def.Bool: - return b; - case TypeDef.Def.U8: - return (byte)unsigned; - case TypeDef.Def.U16: - return (ushort)unsigned; - case TypeDef.Def.U32: - return (uint)unsigned; - case TypeDef.Def.U64: - return unsigned; - case TypeDef.Def.U128: - throw new InvalidOperationException("U128 not supported in C#"); - - case TypeDef.Def.I8: - return (byte)signed; - case TypeDef.Def.I16: - return (ushort)signed; - case TypeDef.Def.I32: - return (int)signed; - case TypeDef.Def.I64: - return signed; - case TypeDef.Def.I128: - throw new InvalidOperationException("I128 not supported in C#"); - - case TypeDef.Def.String: - return str; - case TypeDef.Def.Bytes: - if (bytes == null) - throw new InvalidOperationException("byte array is null!"); - return bytes; - case TypeDef.Def.Hash: - return hash; - case TypeDef.Def.F32: - return f32; - case TypeDef.Def.F64: - return f64; - case TypeDef.Def.Tuple: - return tupleElements; - case TypeDef.Def.Vec: - return vec; - } - - throw new InvalidOperationException($"Type not supported yet! {def}"); - } - - public object GetValue(TypeDef def) - { - return GetValue(def.Type); - } - - public static TypeValue GetTuple(TypeDef def, TypeValue[] tupleValues) - { - return new TypeValue - { - typeDef = def, - tupleElements = tupleValues, - }; - } - - public static TypeValue GetVec(TypeDef memberType, IEnumerable values) - { - return new TypeValue - { - typeDef = TypeDef.GetVec(memberType), - vec = new List(values), - }; - } - } - - public struct Hash : IEquatable - { - private byte[] bytes; - - public static int SIZE = 32; - - public byte[] Bytes => bytes; - - public static TypeDef GetTypeDef() - { - return TypeDef.BuiltInType(TypeDef.Def.Hash); - } - - public static explicit operator Hash(TypeValue v) => (Hash)v.GetValue(GetTypeDef()); - - public static Hash From(byte[] bytes) - { - // TODO: should we validate length here? - return new Hash - { - bytes = bytes, - }; - } - - public bool Equals(Hash other) - { - return bytes.SequenceEqual(other.bytes); - } - - public override bool Equals(object o) { - return o is Hash other && Equals(other); - } - - public static bool operator ==(Hash a, Hash b) => a.Equals(b); - public static bool operator !=(Hash a, Hash b) => !a.Equals(b); - - public override int GetHashCode() { - if (bytes == null) - { - throw new InvalidOperationException("Cannot hash on null bytes."); - } - - return bytes.GetHashCode(); - } - } -} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs.meta deleted file mode 100644 index 7306cba35a6..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/TypeDef.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 6ebc8a2d7cebaea6e9e6bd87e94781bd -timeCreated: 1657552127 \ No newline at end of file From 0a52df60813ea4a2b19af9e5ae1f0de6d079b0ff Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Mon, 27 Feb 2023 18:16:48 -0600 Subject: [PATCH 017/223] SDK Upload Script (#7) * Upload script to help deploying to our partners * You have to specify hosts individually * Small fix * Another small fix - tested + working --------- Co-authored-by: John Detter --- sdks/csharp/upload.sh | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100755 sdks/csharp/upload.sh diff --git a/sdks/csharp/upload.sh b/sdks/csharp/upload.sh new file mode 100755 index 00000000000..b6da31dccee --- /dev/null +++ b/sdks/csharp/upload.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -euo pipefail + +usage() { + echo "Usage: upload.sh " +} + +if [ "$#" != 2 ] ; then + usage + exit 1 +fi + +if [ ! -f "$1" ] ; then + usage + echo "File not found: $1" + exit +fi + +echo "Make sure you have used \"export.sh\" to regenerate the SpacetimeDBUnitySDK." +echo +echo "We will be uploading this SDK to $2" +echo "Your current branch is $(git rev-parse --abbrev-ref HEAD)" +echo +echo "If everything looks correct, press [Enter] now to continue." +read -rp "" + +scp -oStrictHostKeyChecking=no -i "$1" "SpacetimeDBUnitySDK.unitypackage" "root@${2}:/var/www/sdk/SpacetimeDBUnitySDK.unitypackage" +ssh -oStrictHostKeyChecking=no -i "$1" "root@${2}" "chown -R jenkins:jenkins /var/www/sdk" +echo "Upload success." From 93cd63d5674a73667e961c9a35aa3cb444be1bad Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Wed, 8 Mar 2023 11:39:54 -0600 Subject: [PATCH 018/223] Json Byte Arrays Serialized as Hex (#8) * Serialize byte arrays as hex * Fix namespace * Small fix --------- Co-authored-by: John Detter --- .../SpacetimeDB/Scripts/ByteArrayConverter.cs | 23 +++++++++++++++++++ .../Scripts/ByteArrayConverter.cs.meta | 3 +++ 2 files changed, 26 insertions(+) create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs new file mode 100644 index 00000000000..f2797cce33f --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs @@ -0,0 +1,23 @@ +using System; +using Newtonsoft.Json; + +namespace SpacetimeDB +{ + public class ByteArrayConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return objectType == typeof(byte[]); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(BitConverter.ToString((byte[])value).Replace("-","");); + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta new file mode 100644 index 00000000000..d5f933bc806 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 78474f4967ff4b7088056119b4a61e9c +timeCreated: 1677788493 \ No newline at end of file From 02cbdd03b797fd7e46682ee43e19e6d029598b7f Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Tue, 21 Mar 2023 14:53:08 -0500 Subject: [PATCH 019/223] C# Enum Generation (#9) * First pass * Committing meta file * Removed option type - unneeded * Implementing new some converter * Some converter updates * Tons of fixes here * Cleaned up the some/enum serialization implementation --------- Co-authored-by: John Detter --- .../SpacetimeDB/Scripts/ByteArrayConverter.cs | 2 +- .../Scripts/ByteArrayConverter.cs.meta | 12 +++- .../SpacetimeDB/Scripts/NetworkManager.cs | 16 ++--- .../Assets/SpacetimeDB/Scripts/Reducer.cs | 2 +- .../SpacetimeDB/Scripts/ReducerExtensions.cs | 5 ++ .../SpacetimeDB/Scripts/SATS/AlgebraicType.cs | 12 ++++ .../Assets/SpacetimeDB/Scripts/json.meta | 3 + .../SpacetimeDB/Scripts/json/EnumAttribute.cs | 12 ++++ .../Scripts/json/EnumAttribute.cs.meta | 11 +++ .../SpacetimeDB/Scripts/json/EnumWrapper.cs | 16 +++++ .../Scripts/json/EnumWrapper.cs.meta | 11 +++ .../Scripts/json/EnumWrapperConverter.cs | 33 +++++++++ .../Scripts/json/EnumWrapperConverter.cs.meta | 11 +++ .../Scripts/json/JsonContractResolver.cs | 70 +++++++++++++++++++ .../Scripts/json/JsonContractResolver.cs.meta | 11 +++ .../SpacetimeDB/Scripts/json/SomeAttribute.cs | 12 ++++ .../Scripts/json/SomeAttribute.cs.meta | 11 +++ .../SpacetimeDB/Scripts/json/SomeWrapper.cs | 16 +++++ .../Scripts/json/SomeWrapper.cs.meta | 11 +++ .../Scripts/json/SomeWrapperConverter.cs | 29 ++++++++ .../Scripts/json/SomeWrapperConverter.cs.meta | 3 + 21 files changed, 296 insertions(+), 13 deletions(-) create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs.meta create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs index f2797cce33f..6c4bfcd34c9 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs @@ -17,7 +17,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - writer.WriteValue(BitConverter.ToString((byte[])value).Replace("-","");); + writer.WriteValue(BitConverter.ToString((byte[])value).Replace("-", string.Empty)); } } } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta index d5f933bc806..d45f1177c1d 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta @@ -1,3 +1,11 @@ fileFormatVersion: 2 -guid: 78474f4967ff4b7088056119b4a61e9c -timeCreated: 1677788493 \ No newline at end of file +guid: b5f921925c3e131a881439e1ae3278cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index f517752a106..b9bff01a8a6 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -91,6 +91,7 @@ private struct DbEvent private bool connectionClosed; public static ClientCache clientDB; public static Dictionary reducerEventCache = new Dictionary(); + public static Dictionary deserializeEventCache = new Dictionary(); private Thread messageProcessThread; @@ -153,6 +154,10 @@ protected void Awake() { reducerEventCache.Add(reducerEvent.FunctionName, methodInfo); } + if (methodInfo.GetCustomAttribute() is { } deserializeEvent) + { + deserializeEventCache.Add(deserializeEvent.FunctionName, methodInfo); + } } messageProcessThread = new Thread(ProcessMessages); @@ -426,15 +431,8 @@ private string GetTokenKey() return key; } - internal void InternalCallReducer(string reducer, object[] args) + internal void InternalCallReducer(string json) { - // var argBytes = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(args)); - var message = new ReducerCallRequest - { - fn = reducer, - args = args, - }; - var json = JsonConvert.SerializeObject(message); webSocket.Send(Encoding.ASCII.GetBytes("{ \"call\": " + json + " }")); } @@ -454,4 +452,4 @@ private void Update() } } } -} \ No newline at end of file +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs index 9bc7d99a10b..980729fddde 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using UnityEngine; -namespace SpacetimeDB +namespace Bitcraft { public partial class Reducer { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs index 12dedf74eca..0709153d6c6 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs @@ -5,5 +5,10 @@ namespace SpacetimeDB public class ReducerEvent : Attribute { public string FunctionName { get; set; } + } + + public class DeserializeEvent : Attribute + { + public string FunctionName { get; set; } } } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs index 76c177b2dae..d499a11de89 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs @@ -157,6 +157,18 @@ public static AlgebraicType CreateProductType(IEnumerable el } }; } + + public static AlgebraicType CreateSumType(IEnumerable variants) + { + return new AlgebraicType + { + type = Type.Sum, + sum = new SumType + { + variants = variants.ToList(), + } + }; + } public static AlgebraicType CreateArrayType(AlgebraicType elementType) { return new AlgebraicType diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json.meta new file mode 100644 index 00000000000..fec54b6bf03 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: de6efa325d604424a3669ae63df7570a +timeCreated: 1678986584 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs new file mode 100644 index 00000000000..0645d6a39a6 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SpacetimeDB +{ + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] + public class EnumAttribute : Attribute + { + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs.meta new file mode 100644 index 00000000000..968f4566f0f --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aabe537e4e1a029c8a000f7c897a6c86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs new file mode 100644 index 00000000000..169a26e7afe --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SpacetimeDB +{ + public class EnumWrapper + { + public T Value { get; set; } + + public EnumWrapper(T value) + { + Value = value; + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs.meta new file mode 100644 index 00000000000..a001105360e --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ae97cb73962d92e5950bf5185a58867 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs new file mode 100644 index 00000000000..839db9a6229 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Namespace; +using Newtonsoft.Json; +using UnityEngine; + +namespace SpacetimeDB +{ + public class EnumWrapperConverter : JsonConverter + { + public override bool CanConvert(Type objectType) => objectType == typeof(EnumWrapper<>); + + public override object ReadJson( + JsonReader reader, + Type objectType, + object existingValue, + JsonSerializer serializer + ) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteStartObject(); + writer.WritePropertyName(value.ToString()); + writer.WriteRaw("{}"); + writer.WriteEndObject(); + + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs.meta new file mode 100644 index 00000000000..87167287bc4 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb3caa783c4812721a44bf70b400f1f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs new file mode 100644 index 00000000000..678ba6f8d31 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs @@ -0,0 +1,70 @@ +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using UnityEngine; + +namespace SpacetimeDB +{ + public class SomeConverter : JsonConverter + { + public override bool CanConvert(Type objectType) => true; + + public override object ReadJson( + JsonReader reader, + Type objectType, + object existingValue, + JsonSerializer serializer + ) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteStartObject(); + writer.WritePropertyName("some"); + serializer.Serialize(writer, value); + writer.WriteEndObject(); + } + } + + public class EnumConverter : JsonConverter + { + public override bool CanConvert(Type objectType) => true; + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteStartObject(); + writer.WritePropertyName(value.ToString()); + writer.WriteRaw("{}"); + writer.WriteEndObject(); + } + } + + public class JsonContractResolver : DefaultContractResolver + { + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + var property = base.CreateProperty(member, memberSerialization); + + if (member.GetCustomAttribute() != null) + { + property.Converter = new SomeConverter(); + } else if (member.GetCustomAttribute() != null) + { + property.Converter = new EnumConverter(); + } + + return property; + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs.meta new file mode 100644 index 00000000000..f54a3c0bbc8 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ddeb872a1a67e356a06833ee11f999e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs new file mode 100644 index 00000000000..b8bdd44c7d3 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SpacetimeDB +{ + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] + public class SomeAttribute : Attribute + { + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs.meta new file mode 100644 index 00000000000..bdbd6f229ec --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12d996a60ab2e81e485ec27d7573f88d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs new file mode 100644 index 00000000000..8db5f0258fe --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace Namespace +{ + public class SomeWrapper + { + public T Value { get; set; } + + public SomeWrapper(T value) + { + Value = value; + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs.meta new file mode 100644 index 00000000000..458e7e19da4 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45776400b00fadb8b987dcf21080d569 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs new file mode 100644 index 00000000000..b5f2640007f --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs @@ -0,0 +1,29 @@ +using System; +using Namespace; +using Newtonsoft.Json; + +namespace SpacetimeDB +{ + public class SomeWrapperConverter : JsonConverter + { + public override bool CanConvert(Type objectType) => objectType == typeof(SomeWrapper<>); + + public override object ReadJson( + JsonReader reader, + Type objectType, + object existingValue, + JsonSerializer serializer + ) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteStartObject(); + writer.WritePropertyName("some"); + serializer.Serialize(writer, value); + writer.WriteEndObject(); + } + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs.meta new file mode 100644 index 00000000000..4e0539069d5 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f7b5f73c03cf8e9f8b7a37eb90a581bc +timeCreated: 1678986597 \ No newline at end of file From ac573a0d8e49e538b0f344b293ebaca049e9390b Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 23 Mar 2023 11:55:06 -0500 Subject: [PATCH 020/223] Fix compilation issue (#11) Co-authored-by: John --- sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs index 980729fddde..9bc7d99a10b 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using UnityEngine; -namespace Bitcraft +namespace SpacetimeDB { public partial class Reducer { From fdca2f56a9759dacd3806af5166fdcee3dce12f9 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 23 Mar 2023 21:41:47 -0500 Subject: [PATCH 021/223] Automatically find Unity on macOS (#12) Co-authored-by: John Detter --- sdks/csharp/export.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sdks/csharp/export.sh b/sdks/csharp/export.sh index de896251153..32e56df1925 100755 --- a/sdks/csharp/export.sh +++ b/sdks/csharp/export.sh @@ -1,7 +1,16 @@ #!/bin/bash if [ -z "$UNITY_PATH" ]; then - export UNITY_PATH="$HOME/Unity/Hub/Editor/2020.3.25f1/Editor/Unity" + unameOut="$(uname -s)" + case "${unameOut}" in + Linux*) export UNITY_PATH="$HOME/Unity/Hub/Editor/2020.3.25f1/Editor/Unity";; + Darwin*) export UNITY_PATH="/Applications/Unity/Hub/Editor/2020.3.25f1/Unity.app/Contents/MacOS/Unity";; + CYGWIN*) echo "Windows not supported, use WSL instead." && exit 1;; + MINGW*) echo "Windows not supported, use WSL instead." && exit 1;; + *) machine="UNKNOWN:${unameOut}" + esac + echo ${machine} + fi if [ ! -f $UNITY_PATH ]; then From 5839fd4c615c813092f8c9fb8e4086383a30212f Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Fri, 7 Apr 2023 14:51:50 -0500 Subject: [PATCH 022/223] GetEntries now returns both AlgebraicValue and object as a tuple (#15) Co-authored-by: John Detter --- sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index a3e9492ff89..9170291825c 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -159,7 +159,7 @@ public IEnumerable GetObjects(string name) } } - public IEnumerable GetEntries(string name) + public IEnumerable<(AlgebraicValue, object)> GetEntries(string name) { if (!tables.TryGetValue(name, out var table)) { @@ -168,7 +168,7 @@ public IEnumerable GetEntries(string name) foreach (var entry in table.entries) { - yield return entry.Value.Item1; + yield return entry.Value; } } From 3d2a2a87a8968d39312e63221023a675c7bd52cd Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Fri, 7 Apr 2023 14:51:59 -0500 Subject: [PATCH 023/223] Use Network Thread for Processing DB Rows (#14) * Several updates to the way ClientCache + processing updates works * Client cache changes working * Removed log statements --------- Co-authored-by: John Detter --- .../Assets/SpacetimeDB/Scripts/ClientCache.cs | 81 ++++-- .../SpacetimeDB/Scripts/NetworkManager.cs | 264 ++++++++++-------- 2 files changed, 211 insertions(+), 134 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index 9170291825c..8d01f572f35 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -4,6 +4,7 @@ using System.ComponentModel.Design; using System.Linq; using System.Net.Http.Headers; +using System.Reflection; using Google.Protobuf; using UnityEngine; using ClientApi; @@ -44,12 +45,28 @@ public int GetHashCode(byte[] key) // Maps from primary key to type value public readonly Dictionary entries; + // Maps from primary key to decoded value public readonly ConcurrentDictionary decodedValues; - public Type ClientTableType { get => clientTableType; } - public string Name { get => name; } - public AlgebraicType RowSchema { get => rowSchema; } + public Type ClientTableType + { + get => clientTableType; + } + + public MethodInfo InsertCallback; + public MethodInfo DeleteCallback; + public MethodInfo RowUpdatedCallback; + + public string Name + { + get => name; + } + + public AlgebraicType RowSchema + { + get => rowSchema; + } public TableCache(Type clientTableType, AlgebraicType rowSchema, Func decoderFunc) { @@ -58,46 +75,67 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func(new ByteArrayComparer()); decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); } - public (AlgebraicValue, object) Decode(byte[] pk, AlgebraicValue value) + public bool GetDecodedValue(byte[] pk, out AlgebraicValue value, out object obj) { if (decodedValues.TryGetValue(pk, out var decoded)) { - return decoded; + value = decoded.Item1; + obj = decoded.Item2; + return true; } - if (value == null) + value = null; + obj = null; + return false; + } + + /// + /// Decodes the given AlgebraicValue into the out parameter `obj`. + /// + /// The primary key of the row associated with `value`. + /// The AlgebraicValue to decode. + /// The domain object for `value` + public void SetDecodedValue(byte[] pk, AlgebraicValue value, out object obj) + { + if (decodedValues.TryGetValue(pk, out var existingObj)) { - return (null, null); + obj = existingObj.Item2; } - decoded = (value, decoderFunc(value)); - decodedValues[pk] = decoded; - return decoded; - } + else + { + var decoded = (value, decoderFunc(value)); + decodedValues[pk] = decoded; + obj = decoded.Item2; + } + } /// /// Inserts the value into the table. There can be no existing value with the provided pk. /// /// - public object Insert(byte[] rowPk) + public object InsertEntry(byte[] rowPk) { if (entries.TryGetValue(rowPk, out _)) { return null; } - var decodedTuple = Decode(rowPk, null); - if (decodedTuple.Item1 != null && decodedTuple.Item2 != null) + if (GetDecodedValue(rowPk, out var value, out var obj)) { - entries[rowPk] = (decodedTuple.Item1, decodedTuple.Item2); - return decodedTuple.Item2; + entries[rowPk] = (value, obj); + return obj; } // Read failure - Debug.LogError($"Read error when converting row value for table: {name} (version issue?)"); + Debug.LogError( + $"Read error when converting row value for table: {clientTableType.Name} rowPk={Convert.ToBase64String(rowPk)} (version issue?)"); return null; } @@ -108,7 +146,7 @@ public object Insert(byte[] rowPk) /// The primary key that uniquely identifies this row /// The new for the table entry /// True when the old value was removed and the new value was inserted. - public bool Update(ByteString pk, ByteString newValueByteString) + public bool UpdateEntry(ByteString pk, ByteString newValueByteString) { // We have to figure out if pk is going to change or not throw new InvalidOperationException(); @@ -119,7 +157,7 @@ public bool Update(ByteString pk, ByteString newValueByteString) /// /// The primary key that uniquely identifies this row /// - public object Delete(byte[] rowPk) + public object DeleteEntry(byte[] rowPk) { if (entries.TryGetValue(rowPk, out var value)) { @@ -131,7 +169,8 @@ public object Delete(byte[] rowPk) } } - private readonly ConcurrentDictionary tables = new ConcurrentDictionary(); + private readonly ConcurrentDictionary tables = + new ConcurrentDictionary(); public void AddTable(Type clientTableType, AlgebraicType tableRowDef, Func decodeFunc) { @@ -146,6 +185,7 @@ public void AddTable(Type clientTableType, AlgebraicType tableRowDef, Func GetObjects(string name) { if (!tables.TryGetValue(name, out var table)) @@ -189,6 +229,7 @@ public int Count(string name) { return 0; } + return table.entries.Count; } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index b9bff01a8a6..34c9865b788 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -10,10 +10,13 @@ using System.Threading; using System.Threading.Tasks; using ClientApi; +using Google.Protobuf; +using Google.Protobuf.WellKnownTypes; using Newtonsoft.Json; using SpacetimeDB; using SpacetimeDB.SATS; using UnityEngine; +using Event = ClientApi.Event; namespace SpacetimeDB { @@ -39,10 +42,11 @@ public class SubscriptionRequest private struct DbEvent { - public Type clientTableType; + public ClientCache.TableCache table; + public byte[] rowPk; public TableOp op; - public object oldValue; public object newValue; + public object oldValue; } public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue); @@ -154,18 +158,26 @@ protected void Awake() { reducerEventCache.Add(reducerEvent.FunctionName, methodInfo); } + if (methodInfo.GetCustomAttribute() is { } deserializeEvent) { deserializeEventCache.Add(deserializeEvent.FunctionName, methodInfo); } } - + messageProcessThread = new Thread(ProcessMessages); messageProcessThread.Start(); } + struct ProcessedMessage + { + public Message message; + public IList events; + } + private readonly BlockingCollection _messageQueue = new BlockingCollection(); - private readonly ConcurrentQueue _completedMessages = new ConcurrentQueue(); + private readonly ConcurrentQueue _completedMessages = new ConcurrentQueue(); + void ProcessMessages() { @@ -185,40 +197,97 @@ void ProcessMessages() break; } + var (m, events) = PreProcessMessage(bytes); + _completedMessages.Enqueue(new ProcessedMessage + { + message = m, + events = events, + }); + } + + (Message, List) PreProcessMessage(byte[] bytes) + { + var dbEvents = new List(); + var message = ClientApi.Message.Parser.ParseFrom(bytes); + using var stream = new MemoryStream(); + using var reader = new BinaryReader(stream); + + SubscriptionUpdate subscriptionUpdate = null; + switch (message.TypeCase) + { + case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + subscriptionUpdate = message.SubscriptionUpdate; + break; + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; + break; + } + switch (message.TypeCase) { case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: case ClientApi.Message.TypeOneofCase.TransactionUpdate: - { // First apply all of the state - System.Diagnostics.Debug.Assert(subscriptionUpdate != null, - nameof(subscriptionUpdate) + " != null"); - using var stream = new MemoryStream(); - using var reader = new BinaryReader(stream); foreach (var update in subscriptionUpdate.TableUpdates) { + var tableName = update.TableName; + var table = clientDB.GetTable(tableName); + if (table == null) + { + Debug.LogError($"Unknown table name: {tableName}"); + continue; + } + foreach (var row in update.TableRowOperations) { + var rowPk = row.RowPk.ToByteArray(); + var rowValue = row.Row.ToByteArray(); stream.Position = 0; - stream.SetLength(row.Row.Length); - stream.Write(row.Row.ToByteArray(), 0, row.Row.Length); + stream.Write(rowValue, 0, rowValue.Length); stream.Position = 0; - var table = clientDB.GetTable(update.TableName); - var algebraicType = table.RowSchema; - var algebraicValue = AlgebraicValue.Deserialize(algebraicType, reader); - if (algebraicValue != null) + stream.SetLength(rowValue.Length); + + switch (row.Op) { - // Here we are decoding on our message thread so that by the time we get to the - // main thread the cache is already warm. - table.Decode(row.RowPk.ToByteArray(), algebraicValue); + case TableRowOperation.Types.OperationType.Delete: + dbEvents.Add(new DbEvent + { + table = table, + rowPk = rowPk, + op = TableOp.Delete, + newValue = null, + // We cannot grab the old value here because there might be other + // pending operations that will execute before us. We should only + // set this value on the main thread where we know there are no other + // operations which could remove this value. + oldValue = null, + }); + break; + case TableRowOperation.Types.OperationType.Insert: + var algebraicValue = AlgebraicValue.Deserialize(table.RowSchema, reader); + Debug.Assert(algebraicValue != null); + table.SetDecodedValue(rowPk, algebraicValue, out var obj); + dbEvents.Add(new DbEvent + { + table = table, + rowPk = rowPk, + op = TableOp.Insert, + newValue = obj, + oldValue = null, + }); + break; } } } - } + + break; + case ClientApi.Message.TypeOneofCase.IdentityToken: + break; + case ClientApi.Message.TypeOneofCase.Event: break; } - _completedMessages.Enqueue(bytes); + return (message, dbEvents); } } @@ -258,13 +327,8 @@ public void Connect(string host, string addressOrName, bool sslEnabled = true) }); } - readonly List _dbEvents = new List(); - - private void OnMessageProcessComplete(byte[] bytes) + private void OnMessageProcessComplete(Message message, IList events) { - _dbEvents.Clear(); - var message = ClientApi.Message.Parser.ParseFrom(bytes); - SubscriptionUpdate subscriptionUpdate = null; switch (message.TypeCase) { @@ -281,109 +345,81 @@ private void OnMessageProcessComplete(byte[] bytes) case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: case ClientApi.Message.TypeOneofCase.TransactionUpdate: // First apply all of the state - foreach (var update in subscriptionUpdate.TableUpdates) + for (var i = 0; i < events.Count; i++) { - var tableName = update.TableName; - var table = clientDB.GetTable(tableName); - if (table == null) + var ev = events[i]; + switch (ev.op) { - continue; + case TableOp.Delete: + ev.oldValue = events[i].table.DeleteEntry(ev.rowPk); + events[i] = ev; + break; + case TableOp.Insert: + ev.newValue = events[i].table.InsertEntry(ev.rowPk); + events[i] = ev; + break; } + } - foreach (var row in update.TableRowOperations) - { - var rowPk = row.RowPk.ToByteArray(); + // Send out events + var eventCount = events.Count; + for (var i = 0; i < eventCount; i++) + { + var tableName = events[i].table.ClientTableType.Name; + var tableOp = events[i].op; + var oldValue = events[i].oldValue; + var newValue = events[i].newValue; - switch (row.Op) + switch (tableOp) + { + case TableOp.Insert: { - case TableRowOperation.Types.OperationType.Delete: - var deletedValue = table.Delete(rowPk); - if (deletedValue != null) + if (events[i].table.InsertCallback != null) + { + if (oldValue == null && newValue != null) { - _dbEvents.Add(new DbEvent + events[i].table.InsertCallback.Invoke(null, new[] { newValue }); + if (events[i].table.RowUpdatedCallback != null) { - clientTableType = table.ClientTableType, - op = TableOp.Delete, - newValue = null, - oldValue = deletedValue, - }); + events[i].table.RowUpdatedCallback + .Invoke(null, new[] { tableOp, null, newValue }); + } } - - break; - case TableRowOperation.Types.OperationType.Insert: - var insertedValue = table.Insert(rowPk); - if (insertedValue != null) + else { - _dbEvents.Add(new DbEvent - { - clientTableType = table.ClientTableType, - op = TableOp.Insert, - newValue = insertedValue, - oldValue = null - }); + Debug.LogError("Failed to send callback: invalid insert!"); } + } - break; + break; } - } - } - - // Send out events - var eventCount = _dbEvents.Count; - for (int i = 0; i < eventCount; i++) - { - string tableName = _dbEvents[i].clientTableType.Name; - - bool isUpdate = false; - if (i < eventCount - 1) - { - if (_dbEvents[i].op == TableOp.Delete && _dbEvents[i + 1].op == TableOp.Insert) + case TableOp.Delete: { - // somewhat hacky: Delete followed by an insert on the same table is considered an update. - isUpdate = tableName.Equals(_dbEvents[i + 1].clientTableType.Name); - } - } - - TableOp tableOp = _dbEvents[i].op; - - object oldValue = _dbEvents[i].oldValue, newValue = _dbEvents[i].newValue; - - if (isUpdate) - { - // Merge delete and insert in one update - tableOp = TableOp.Update; - newValue = _dbEvents[i + 1].newValue; - - i++; + if (events[i].table.DeleteCallback != null) + { + if (oldValue != null && newValue == null) + { + events[i].table.DeleteCallback.Invoke(null, new[] { oldValue }); + if (events[i].table.RowUpdatedCallback != null) + { + events[i].table.RowUpdatedCallback + .Invoke(null, new[] { tableOp, oldValue, null }); + } + } + else + { + Debug.LogError("Failed to send callback: invalid delete"); + } + } - var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnUpdateEvent"); - if (clientEvent != null) - { - clientEvent.Invoke(null, new object[] { oldValue, newValue }); - } - } - else if (tableOp == TableOp.Insert) - { - var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnInsertEvent"); - if (clientEvent != null) - { - clientEvent.Invoke(null, new object[] { newValue }); - } - } - else if (tableOp == TableOp.Delete) - { - var clientEvent = _dbEvents[i].clientTableType.GetMethod("OnDeleteEvent"); - if (clientEvent != null) - { - clientEvent.Invoke(null, new object[] { oldValue }); + break; } + case TableOp.Update: + throw new NotImplementedException(); + default: + throw new ArgumentOutOfRangeException(); } - var clientRowUpdate = _dbEvents[i].clientTableType.GetMethod("OnRowUpdateEvent"); - if (clientRowUpdate != null) - { - clientRowUpdate.Invoke(null, new object[] { tableOp, oldValue, newValue }); - } onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue); } @@ -435,7 +471,7 @@ internal void InternalCallReducer(string json) { webSocket.Send(Encoding.ASCII.GetBytes("{ \"call\": " + json + " }")); } - + public void Subscribe(List queries) { var json = JsonConvert.SerializeObject(queries); @@ -448,8 +484,8 @@ private void Update() while (_completedMessages.TryDequeue(out var result)) { - OnMessageProcessComplete(result); + OnMessageProcessComplete(result.message, result.events); } } } -} +} \ No newline at end of file From a9b9bfc735617a56248def6312a853ab32630de0 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Fri, 21 Apr 2023 13:13:54 -0500 Subject: [PATCH 024/223] State Diffs (#16) * Copied changes from BitCraft * Applied state diff changes * State diffs complete * Compilation fix * Fix build issues --------- Co-authored-by: John Detter --- .../Assets/SpacetimeDB/Scripts/ClientCache.cs | 19 +- .../SpacetimeDB/Scripts/NetworkManager.cs | 211 ++++++++++++------ 2 files changed, 162 insertions(+), 68 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index 8d01f572f35..8726452d51c 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -16,7 +16,7 @@ public class ClientCache { public class TableCache { - private class ByteArrayComparer : IEqualityComparer + public class ByteArrayComparer : IEqualityComparer { public bool Equals(byte[] left, byte[] right) { @@ -56,6 +56,8 @@ public Type ClientTableType public MethodInfo InsertCallback; public MethodInfo DeleteCallback; + public MethodInfo UpdateCallback; + // TODO: Consider renaming this one, this kind of implies that its a callback for the Update operation public MethodInfo RowUpdatedCallback; public string Name @@ -77,6 +79,7 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func(new ByteArrayComparer()); decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); @@ -122,9 +125,10 @@ public void SetDecodedValue(byte[] pk, AlgebraicValue value, out object obj) /// public object InsertEntry(byte[] rowPk) { - if (entries.TryGetValue(rowPk, out _)) + if (entries.TryGetValue(rowPk, out var existingValue)) { - return null; + Debug.LogWarning($"We tried to insert a database row that already exists. table={Name} RowPK={Convert.ToBase64String(rowPk)}"); + return existingValue.Item2; } if (GetDecodedValue(rowPk, out var value, out var obj)) @@ -165,6 +169,15 @@ public object DeleteEntry(byte[] rowPk) return value.Item2; } + // SpacetimeDB is asking us to delete something we don't have, this makes no sense. We can + // fabricate the deletion by trying to look it up in our local decode table. + if (decodedValues.TryGetValue(rowPk, out var decodedValue)) + { + Debug.LogWarning("Deleting value that we don't have (using cached value)"); + return decodedValue.Item2; + } + + Debug.LogWarning("Deleting value that we don't have (no cached value available)"); return null; } } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 34c9865b788..f80ec593985 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Net.WebSockets; using System.Reflection; +using System.Runtime.Remoting.Channels; using System.Text; using System.Text.RegularExpressions; using System.Threading; @@ -132,9 +133,8 @@ protected void Awake() clientDB = new ClientCache(); var type = typeof(IDatabaseTable); - var types = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(s => s.GetTypes()) - .Where(p => type.IsAssignableFrom(p)); + var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes()) + .Where(p => type.IsAssignableFrom(p)); foreach (var @class in types) { if (!@class.IsClass) @@ -144,22 +144,26 @@ protected void Awake() var algebraicTypeFunc = @class.GetMethod("GetAlgebraicType", BindingFlags.Static | BindingFlags.Public); var algebraicValue = algebraicTypeFunc!.Invoke(null, null) as AlgebraicType; - var conversionFunc = @class.GetMethods().FirstOrDefault(a => - a.Name == "op_Explicit" && a.GetParameters().Length > 0 && - a.GetParameters()[0].ParameterType == typeof(AlgebraicValue)); + var conversionFunc = @class.GetMethods() + .FirstOrDefault(a => a.Name == "op_Explicit" && + a.GetParameters().Length > 0 && + a.GetParameters()[0].ParameterType == + typeof(AlgebraicValue)); clientDB.AddTable(@class, algebraicValue, - a => { return conversionFunc!.Invoke(null, new object[] { a }); }); + a => { return conversionFunc!.Invoke(null, new object[] { a }); }); } // cache all our reducer events by their function name - foreach (var methodInfo in typeof(SpacetimeDB.Reducer).GetMethods()) + foreach (var methodInfo in typeof(Reducer).GetMethods()) { - if (methodInfo.GetCustomAttribute() is { } reducerEvent) + if (methodInfo.GetCustomAttribute() is + { } reducerEvent) { reducerEventCache.Add(reducerEvent.FunctionName, methodInfo); } - if (methodInfo.GetCustomAttribute() is { } deserializeEvent) + if (methodInfo.GetCustomAttribute() is + { } deserializeEvent) { deserializeEventCache.Add(deserializeEvent.FunctionName, methodInfo); } @@ -175,34 +179,26 @@ struct ProcessedMessage public IList events; } - private readonly BlockingCollection _messageQueue = new BlockingCollection(); - private readonly ConcurrentQueue _completedMessages = new ConcurrentQueue(); - + private readonly BlockingCollection _messageQueue = new BlockingCollection(new ConcurrentQueue()); + private ProcessedMessage? nextMessage; void ProcessMessages() { while (true) { var bytes = _messageQueue.Take(); - - var message = ClientApi.Message.Parser.ParseFrom(bytes); - SubscriptionUpdate subscriptionUpdate = null; - switch (message.TypeCase) + // Wait for the main thread to consume the message we digested for them + while (nextMessage.HasValue) { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - subscriptionUpdate = message.SubscriptionUpdate; - break; - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; - break; + Thread.Sleep(1); } var (m, events) = PreProcessMessage(bytes); - _completedMessages.Enqueue(new ProcessedMessage + nextMessage = new ProcessedMessage { message = m, events = events, - }); + }; } (Message, List) PreProcessMessage(byte[] bytes) @@ -250,6 +246,14 @@ void ProcessMessages() switch (row.Op) { case TableRowOperation.Types.OperationType.Delete: + // If we don't already have this row, we should skip this delete + if (!table.entries.ContainsKey(rowPk)) + { + Debug.LogError( + $"We received a delete for a row we don't even subscribe to! table={table.Name}"); + continue; + } + dbEvents.Add(new DbEvent { table = table, @@ -264,6 +268,12 @@ void ProcessMessages() }); break; case TableRowOperation.Types.OperationType.Insert: + // If we already have this row, we can ignore it + if (table.entries.ContainsKey(rowPk)) + { + continue; + } + var algebraicValue = AlgebraicValue.Deserialize(table.RowSchema, reader); Debug.Assert(algebraicValue != null); table.SetDecodedValue(rowPk, algebraicValue, out var obj); @@ -287,6 +297,37 @@ void ProcessMessages() break; } + if (message.TypeCase == Message.TypeOneofCase.SubscriptionUpdate) + { + // NOTE: We are going to calculate a local state diff here. This is kind of expensive to do, + // but keep in mind that we're still on the network thread so spending some extra time here + // is acceptable. + if (subscriptionUpdate!.TableUpdates.Any( + a => a.TableRowOperations.Any(b => b.Op == TableRowOperation.Types.OperationType.Delete))) + { + Debug.LogWarning( + "We see delete events in our subscription update, this is unexpected. Likely you should update your SpacetimeDBUnitySDK."); + } + + foreach (var tableUpdate in subscriptionUpdate.TableUpdates) + { + var clientTable = clientDB.GetTable(tableUpdate.TableName); + var newPks = tableUpdate.TableRowOperations + .Where(a => a.Op == TableRowOperation.Types.OperationType.Insert) + .Select(b => b.RowPk.ToByteArray()); + var existingPks = clientTable.entries.Select(a => a.Key); + dbEvents.AddRange(existingPks.Except(newPks, new ClientCache.TableCache.ByteArrayComparer()) + .Select(a => new DbEvent + { + rowPk = a, + newValue = null, + oldValue = clientTable.entries[a].Item2, + op = TableOp.Delete, + table = clientTable, + })); + } + } + return (message, dbEvents); } } @@ -329,25 +370,31 @@ public void Connect(string host, string addressOrName, bool sslEnabled = true) private void OnMessageProcessComplete(Message message, IList events) { - SubscriptionUpdate subscriptionUpdate = null; - switch (message.TypeCase) - { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - subscriptionUpdate = message.SubscriptionUpdate; - break; - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; - break; - } - switch (message.TypeCase) { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - case ClientApi.Message.TypeOneofCase.TransactionUpdate: + case Message.TypeOneofCase.SubscriptionUpdate: + case Message.TypeOneofCase.TransactionUpdate: // First apply all of the state for (var i = 0; i < events.Count; i++) { + // TODO: Reimplement updates when we add support for primary keys var ev = events[i]; + if (i < events.Count - 1) + { + if (events[i].table == events[i + 1].table && events[i].op == TableOp.Delete && + events[i + 1].op == TableOp.Insert) + { + // somewhat hacky: Delete followed by an insert on the same table is considered an update. + ev.oldValue = events[i].table.DeleteEntry(ev.rowPk); + ev.newValue = events[i].table.InsertEntry(events[i + 1].rowPk); + ev.op = TableOp.Update; + events[i] = ev; + + // Skip the next event, this is part of the hack + events.RemoveAt(i + 1); + } + } + switch (ev.op) { case TableOp.Delete: @@ -358,6 +405,10 @@ private void OnMessageProcessComplete(Message message, IList events) ev.newValue = events[i].table.InsertEntry(ev.rowPk); events[i] = ev; break; + case TableOp.Update: + break; + default: + throw new ArgumentOutOfRangeException(); } } @@ -373,88 +424,117 @@ private void OnMessageProcessComplete(Message message, IList events) switch (tableOp) { case TableOp.Insert: - { - if (events[i].table.InsertCallback != null) { if (oldValue == null && newValue != null) { - events[i].table.InsertCallback.Invoke(null, new[] { newValue }); + if (events[i].table.InsertCallback != null) + { + events[i].table.InsertCallback.Invoke(null, new[] { newValue }); + } + if (events[i].table.RowUpdatedCallback != null) { events[i].table.RowUpdatedCallback - .Invoke(null, new[] { tableOp, null, newValue }); + .Invoke(null, new[] { tableOp, null, newValue }); } } else { Debug.LogError("Failed to send callback: invalid insert!"); } - } - break; - } + break; + } case TableOp.Delete: - { - if (events[i].table.DeleteCallback != null) { if (oldValue != null && newValue == null) { - events[i].table.DeleteCallback.Invoke(null, new[] { oldValue }); + if (events[i].table.DeleteCallback != null) + { + events[i].table.DeleteCallback.Invoke(null, new[] { oldValue }); + } + if (events[i].table.RowUpdatedCallback != null) { events[i].table.RowUpdatedCallback - .Invoke(null, new[] { tableOp, oldValue, null }); + .Invoke(null, new[] { tableOp, oldValue, null }); } } else { Debug.LogError("Failed to send callback: invalid delete"); } - } - break; - } + break; + } case TableOp.Update: - throw new NotImplementedException(); + { + if (oldValue != null && newValue != null) + { + if (events[i].table.UpdateCallback != null) + { + events[i].table.UpdateCallback.Invoke(null, new[] { oldValue, newValue }); + } + + if (events[i].table.RowUpdatedCallback != null) + { + events[i].table.RowUpdatedCallback + .Invoke(null, new[] { tableOp, oldValue, null }); + } + } + else + { + Debug.LogError("Failed to send callback: invalid update"); + } + + break; + } default: throw new ArgumentOutOfRangeException(); } - onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue); } switch (message.TypeCase) { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: + case Message.TypeOneofCase.SubscriptionUpdate: onTransactionComplete?.Invoke(); break; - case ClientApi.Message.TypeOneofCase.TransactionUpdate: + case Message.TypeOneofCase.TransactionUpdate: onTransactionComplete?.Invoke(); onEvent?.Invoke(message.TransactionUpdate.Event); var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; - if (reducerEventCache.ContainsKey(functionName)) + if (reducerEventCache.TryGetValue(functionName, out var value)) { - reducerEventCache[functionName] - .Invoke(null, new object[] { message.TransactionUpdate.Event }); + value.Invoke(null, new object[] { message.TransactionUpdate.Event }); } break; + case Message.TypeOneofCase.None: + break; + case Message.TypeOneofCase.FunctionCall: + break; + case Message.TypeOneofCase.Event: + break; + case Message.TypeOneofCase.IdentityToken: + break; + default: + throw new ArgumentOutOfRangeException(); } break; - case ClientApi.Message.TypeOneofCase.IdentityToken: + case Message.TypeOneofCase.IdentityToken: onIdentityReceived?.Invoke(Identity.From(message.IdentityToken.Identity.ToByteArray())); PlayerPrefs.SetString(GetTokenKey(), message.IdentityToken.Token); break; - case ClientApi.Message.TypeOneofCase.Event: + case Message.TypeOneofCase.Event: onEvent?.Invoke(message.Event); break; } } - private void OnMessageReceived(byte[] bytes) => _messageQueue.Add(bytes); private string GetTokenKey() @@ -482,10 +562,11 @@ private void Update() { webSocket.Update(); - while (_completedMessages.TryDequeue(out var result)) + if (nextMessage != null) { - OnMessageProcessComplete(result.message, result.events); + OnMessageProcessComplete(nextMessage.Value.message, nextMessage.Value.events); + nextMessage = null; } } } -} \ No newline at end of file +} From 63f52395b2a62e5e5a905e1b3e2d13760596063a Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Wed, 7 Jun 2023 22:23:52 -0500 Subject: [PATCH 025/223] Primary Key Impl (#18) * Pulled SpacetimeUnitySDK from the BitCraft project * Removed unused logs * Removed primary key functionality * Fix compilation issues with older version of C# * Primary key client implementation * Another row update fix --------- Co-authored-by: John --- .../Assets/SpacetimeDB/Scripts/ClientCache.cs | 23 ++- .../SpacetimeDB/Scripts/NetworkManager.cs | 146 +++++++++++++----- .../Assets/SpacetimeDB/Scripts/Reducer.cs | 2 +- .../Scripts/SATS/AlgebraicValue.cs | 103 +++++++++++- 4 files changed, 226 insertions(+), 48 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index 8726452d51c..6057e883bc0 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -59,6 +59,7 @@ public Type ClientTableType public MethodInfo UpdateCallback; // TODO: Consider renaming this one, this kind of implies that its a callback for the Update operation public MethodInfo RowUpdatedCallback; + public MethodInfo ComparePrimaryKeyFunc; public string Name { @@ -81,6 +82,7 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func(new ByteArrayComparer()); decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); } @@ -127,7 +129,7 @@ public object InsertEntry(byte[] rowPk) { if (entries.TryGetValue(rowPk, out var existingValue)) { - Debug.LogWarning($"We tried to insert a database row that already exists. table={Name} RowPK={Convert.ToBase64String(rowPk)}"); + // Debug.LogWarning($"We tried to insert a database row that already exists. table={Name} RowPK={Convert.ToBase64String(rowPk)}"); return existingValue.Item2; } @@ -180,6 +182,25 @@ public object DeleteEntry(byte[] rowPk) Debug.LogWarning("Deleting value that we don't have (no cached value available)"); return null; } + + public bool ComparePrimaryKey(AlgebraicValue v1, AlgebraicValue v2) + { + return (bool)ComparePrimaryKeyFunc.Invoke(null, new object[] { rowSchema, v1, v2 }); + } + + public bool ComparePrimaryKey(byte[] rowPk1, byte[] rowPk2) + { + if (!decodedValues.TryGetValue(rowPk1, out var v1)) + { + return false; + } + if (!decodedValues.TryGetValue(rowPk2, out var v2)) + { + return false; + } + + return (bool)ComparePrimaryKeyFunc.Invoke(null, new object[] { rowSchema, v1.Item1, v2.Item1 }); + } } private readonly ConcurrentDictionary tables = diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index f80ec593985..af963455fea 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -17,6 +17,7 @@ using SpacetimeDB; using SpacetimeDB.SATS; using UnityEngine; +using UnityEngine.Rendering; using Event = ClientApi.Event; namespace SpacetimeDB @@ -44,10 +45,11 @@ public class SubscriptionRequest private struct DbEvent { public ClientCache.TableCache table; - public byte[] rowPk; public TableOp op; public object newValue; public object oldValue; + public byte[] deletedPk; + public byte[] insertedPk; } public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue); @@ -154,7 +156,7 @@ protected void Awake() } // cache all our reducer events by their function name - foreach (var methodInfo in typeof(Reducer).GetMethods()) + foreach (var methodInfo in typeof(SpacetimeDB.Reducer).GetMethods()) { if (methodInfo.GetCustomAttribute() is { } reducerEvent) @@ -179,7 +181,7 @@ struct ProcessedMessage public IList events; } - private readonly BlockingCollection _messageQueue = new BlockingCollection(new ConcurrentQueue()); + private readonly BlockingCollection _messageQueue = new(new ConcurrentQueue()); private ProcessedMessage? nextMessage; void ProcessMessages() @@ -249,15 +251,23 @@ void ProcessMessages() // If we don't already have this row, we should skip this delete if (!table.entries.ContainsKey(rowPk)) { - Debug.LogError( - $"We received a delete for a row we don't even subscribe to! table={table.Name}"); + if (update.TableRowOperations.Any( + a => a.RowPk.ToByteArray().SequenceEqual(rowPk))) + { + // Debug.LogWarning("We are deleting and inserting the same row in the same TX!"); + } + else + { + Debug.LogWarning( + $"We received a delete for a row we don't even subscribe to! table={table.Name}"); + } continue; } dbEvents.Add(new DbEvent { table = table, - rowPk = rowPk, + deletedPk = rowPk, op = TableOp.Delete, newValue = null, // We cannot grab the old value here because there might be other @@ -280,7 +290,7 @@ void ProcessMessages() dbEvents.Add(new DbEvent { table = table, - rowPk = rowPk, + insertedPk = rowPk, op = TableOp.Insert, newValue = obj, oldValue = null, @@ -296,6 +306,36 @@ void ProcessMessages() case ClientApi.Message.TypeOneofCase.Event: break; } + + // Factor out any insert/deletes into updates + for (var x = 0; x < dbEvents.Count; x++) + { + var insertEvent = dbEvents[x]; + if (insertEvent.op != TableOp.Insert) + { + continue; + } + + for (var y = 0; y < dbEvents.Count; y++) + { + var deleteEvent = dbEvents[y]; + if (deleteEvent.op != TableOp.Delete || deleteEvent.table != insertEvent.table + || !insertEvent.table.ComparePrimaryKey(insertEvent.insertedPk, deleteEvent.deletedPk)) + { + continue; + } + + var updateEvent = new DbEvent { + deletedPk = deleteEvent.deletedPk, + insertedPk = insertEvent.insertedPk, + op = TableOp.Update, + table = insertEvent.table, + }; + dbEvents[x] = updateEvent; + dbEvents.RemoveAt(y); + break; + } + } if (message.TypeCase == Message.TypeOneofCase.SubscriptionUpdate) { @@ -319,7 +359,7 @@ void ProcessMessages() dbEvents.AddRange(existingPks.Except(newPks, new ClientCache.TableCache.ByteArrayComparer()) .Select(a => new DbEvent { - rowPk = a, + deletedPk = a, newValue = null, oldValue = clientTable.entries[a].Item2, op = TableOp.Delete, @@ -379,33 +419,20 @@ private void OnMessageProcessComplete(Message message, IList events) { // TODO: Reimplement updates when we add support for primary keys var ev = events[i]; - if (i < events.Count - 1) - { - if (events[i].table == events[i + 1].table && events[i].op == TableOp.Delete && - events[i + 1].op == TableOp.Insert) - { - // somewhat hacky: Delete followed by an insert on the same table is considered an update. - ev.oldValue = events[i].table.DeleteEntry(ev.rowPk); - ev.newValue = events[i].table.InsertEntry(events[i + 1].rowPk); - ev.op = TableOp.Update; - events[i] = ev; - - // Skip the next event, this is part of the hack - events.RemoveAt(i + 1); - } - } - switch (ev.op) { case TableOp.Delete: - ev.oldValue = events[i].table.DeleteEntry(ev.rowPk); + ev.oldValue = events[i].table.DeleteEntry(ev.deletedPk); events[i] = ev; break; case TableOp.Insert: - ev.newValue = events[i].table.InsertEntry(ev.rowPk); + ev.newValue = events[i].table.InsertEntry(ev.insertedPk); events[i] = ev; break; case TableOp.Update: + ev.oldValue = events[i].table.DeleteEntry(ev.deletedPk); + ev.newValue = events[i].table.InsertEntry(ev.insertedPk); + events[i] = ev; break; default: throw new ArgumentOutOfRangeException(); @@ -424,40 +451,67 @@ private void OnMessageProcessComplete(Message message, IList events) switch (tableOp) { case TableOp.Insert: + if (oldValue == null && newValue != null) { - if (oldValue == null && newValue != null) + try { if (events[i].table.InsertCallback != null) { events[i].table.InsertCallback.Invoke(null, new[] { newValue }); } - + } + catch (Exception e) + { + Debug.LogException(e); + } + + try + { if (events[i].table.RowUpdatedCallback != null) { events[i].table.RowUpdatedCallback .Invoke(null, new[] { tableOp, null, newValue }); } } - else + catch (Exception e) { - Debug.LogError("Failed to send callback: invalid insert!"); + Debug.LogException(e); } - break; } + else + { + Debug.LogError("Failed to send callback: invalid insert!"); + } + + break; case TableOp.Delete: { if (oldValue != null && newValue == null) { if (events[i].table.DeleteCallback != null) { - events[i].table.DeleteCallback.Invoke(null, new[] { oldValue }); + try + { + events[i].table.DeleteCallback.Invoke(null, new[] { oldValue }); + } + catch (Exception e) + { + Debug.LogException(e); + } } if (events[i].table.RowUpdatedCallback != null) { - events[i].table.RowUpdatedCallback + try + { + events[i].table.RowUpdatedCallback .Invoke(null, new[] { tableOp, oldValue, null }); + } + catch (Exception e) + { + Debug.LogException(e); + } } } else @@ -471,15 +525,29 @@ private void OnMessageProcessComplete(Message message, IList events) { if (oldValue != null && newValue != null) { - if (events[i].table.UpdateCallback != null) + try { - events[i].table.UpdateCallback.Invoke(null, new[] { oldValue, newValue }); + if (events[i].table.UpdateCallback != null) + { + events[i].table.UpdateCallback.Invoke(null, new[] { oldValue, newValue }); + } } - - if (events[i].table.RowUpdatedCallback != null) + catch (Exception e) { - events[i].table.RowUpdatedCallback - .Invoke(null, new[] { tableOp, oldValue, null }); + Debug.LogException(e); + } + + try + { + if (events[i].table.RowUpdatedCallback != null) + { + events[i].table.RowUpdatedCallback + .Invoke(null, new[] { tableOp, oldValue, null }); + } + } + catch (Exception e) + { + Debug.LogException(e); } } else diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs index 9bc7d99a10b..52f83947c98 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs @@ -7,4 +7,4 @@ namespace SpacetimeDB public partial class Reducer { } -} \ No newline at end of file +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs index 579ba0dca96..0f4b1e8e8c5 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs @@ -1,13 +1,6 @@ using System; -using System.Collections; using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; -using Google.Protobuf.WellKnownTypes; -using TMPro; -using UnityEditor.Build.Content; -using UnityEngine; -using Type = System.Type; namespace SpacetimeDB.SATS { @@ -221,6 +214,57 @@ byte[] ReadByteArray() throw new NotImplementedException(); } } + + public static bool Compare(BuiltinType t, BuiltinValue v1, BuiltinValue v2) + { + switch (t.type) + { + case BuiltinType.Type.Bool: + return v1.AsBool() == v2.AsBool(); + case BuiltinType.Type.U8: + return v1.AsU8() == v2.AsU8(); + case BuiltinType.Type.I8: + return v1.AsI8() == v2.AsI8(); + case BuiltinType.Type.U16: + return v1.AsU16() == v2.AsU16(); + case BuiltinType.Type.I16: + return v1.AsI16() == v2.AsI16(); + case BuiltinType.Type.U32: + return v1.AsU32() == v2.AsU32(); + case BuiltinType.Type.I32: + return v1.AsI32() == v2.AsI32(); + case BuiltinType.Type.U64: + return v1.AsU64() == v2.AsU64(); + case BuiltinType.Type.I64: + return v1.AsI64() == v2.AsI64(); + case BuiltinType.Type.U128: + case BuiltinType.Type.I128: + case BuiltinType.Type.F32: + case BuiltinType.Type.F64: + case BuiltinType.Type.Map: + throw new NotImplementedException(); + case BuiltinType.Type.String: + return v1.AsString() == v2.AsString(); + case BuiltinType.Type.Array: + var list1 = v1.AsArray(); + var list2 = v2.AsArray(); + if (list1.Count != list2.Count) + { + return false; + } + + for (var i = 0; i < list1.Count; i++) + { + if (!AlgebraicValue.Compare(t.arrayType, list1[i], list2[i])) + { + return false; + } + } + return true; + default: + throw new NotImplementedException(); + } + } } public class SumValue @@ -251,6 +295,16 @@ public void Serialize(SumType type, BinaryWriter writer) writer.Write(tag); value.Serialize(type.variants[tag].algebraicType, writer); } + + public static bool Compare(SumType t, SumValue v1, SumValue v2) + { + if (v1.tag != v2.tag) + { + return false; + } + + return AlgebraicValue.Compare(t.variants[v1.tag].algebraicType, v1.value, v2.value); + } } public class ProductValue @@ -281,6 +335,24 @@ public static ProductValue Deserialize(ProductType type, BinaryReader reader) return result; } + + public static bool Compare(ProductType type, ProductValue v1, ProductValue v2) + { + if (v1.elements.Count != v2.elements.Count) + { + return false; + } + + for (var i = 0; i < type.elements.Count; i++) + { + if(!AlgebraicValue.Compare(type.elements[i].algebraicType, v1.elements[i], v2.elements[i])) + { + return false; + } + } + + return true; + } } public class AlgebraicValue @@ -332,6 +404,23 @@ public class AlgebraicValue public static AlgebraicValue Create(ProductValue value) => new AlgebraicValue { product = value }; public static AlgebraicValue Create(SumValue value) => new AlgebraicValue { sum = value }; + public static bool Compare(AlgebraicType t, AlgebraicValue v1, AlgebraicValue v2) + { + switch (t.type) + { + case AlgebraicType.Type.Builtin: + return BuiltinValue.Compare(t.builtin, v1.builtin, v2.builtin); + case AlgebraicType.Type.Sum: + return SumValue.Compare(t.sum, v1.sum, v2.sum); + case AlgebraicType.Type.Product: + return ProductValue.Compare(t.product, v1.product, v2.product); + case AlgebraicType.Type.TypeRef: + case AlgebraicType.Type.None: + default: + throw new NotImplementedException(); + } + } + public static AlgebraicValue Deserialize(AlgebraicType type, BinaryReader reader) { switch (type.type) From c31362939d7a6ba5af92a356542e4adac80ecfca Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Wed, 7 Jun 2023 22:24:00 -0500 Subject: [PATCH 026/223] SpacetimeDB SDK Version 0.4.1 (#17) * Pulled SpacetimeUnitySDK from the BitCraft project * Removed unused logs * Removed primary key functionality * Fix compilation issues with older version of C# --------- Co-authored-by: John --- sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index af963455fea..c5400df410c 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Net.WebSockets; using System.Reflection; -using System.Runtime.Remoting.Channels; using System.Text; using System.Text.RegularExpressions; using System.Threading; From 5e636316142a25ff93b739f1501ad23837565b61 Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Thu, 8 Jun 2023 19:55:25 -0300 Subject: [PATCH 027/223] Adding event parameter to table callbacks (#19) * Adding event parameter to table callbacks * Reverted a namespace change --------- Co-authored-by: Steve Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> --- .../Assets/SpacetimeDB/Scripts/ClientCache.cs | 26 ++++++++++--------- .../SpacetimeDB/Scripts/NetworkManager.cs | 16 ++++++------ 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index 6057e883bc0..72b83ebb459 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -54,12 +54,12 @@ public Type ClientTableType get => clientTableType; } - public MethodInfo InsertCallback; - public MethodInfo DeleteCallback; - public MethodInfo UpdateCallback; + public Action InsertCallback; + public Action DeleteCallback; + public Action UpdateCallback; // TODO: Consider renaming this one, this kind of implies that its a callback for the Update operation - public MethodInfo RowUpdatedCallback; - public MethodInfo ComparePrimaryKeyFunc; + public Action RowUpdatedCallback; + public Func ComparePrimaryKeyFunc; public string Name { @@ -78,11 +78,13 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func)clientTableType.GetMethod("OnInsertEvent")?.CreateDelegate(typeof(Action)); + DeleteCallback = (Action)clientTableType.GetMethod("OnDeleteEvent")?.CreateDelegate(typeof(Action)); + UpdateCallback = (Action)clientTableType.GetMethod("OnUpdateEvent")?.CreateDelegate(typeof(Action)); + RowUpdatedCallback = (Action)clientTableType.GetMethod("OnRowUpdateEvent") + ?.CreateDelegate(typeof(Action)); + ComparePrimaryKeyFunc = (Func)clientTableType.GetMethod("ComparePrimaryKey", BindingFlags.Static | BindingFlags.Public) + ?.CreateDelegate(typeof(Func)); entries = new Dictionary(new ByteArrayComparer()); decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); } @@ -185,7 +187,7 @@ public object DeleteEntry(byte[] rowPk) public bool ComparePrimaryKey(AlgebraicValue v1, AlgebraicValue v2) { - return (bool)ComparePrimaryKeyFunc.Invoke(null, new object[] { rowSchema, v1, v2 }); + return (bool)ComparePrimaryKeyFunc.Invoke(rowSchema, v1, v2); } public bool ComparePrimaryKey(byte[] rowPk1, byte[] rowPk2) @@ -199,7 +201,7 @@ public bool ComparePrimaryKey(byte[] rowPk1, byte[] rowPk2) return false; } - return (bool)ComparePrimaryKeyFunc.Invoke(null, new object[] { rowSchema, v1.Item1, v2.Item1 }); + return (bool)ComparePrimaryKeyFunc.Invoke(rowSchema, v1.Item1, v2.Item1); } } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index c5400df410c..620b7271e04 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -51,7 +51,7 @@ private struct DbEvent public byte[] insertedPk; } - public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue); + public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, ClientApi.Event dbEvent); /// /// Called when a connection is established to a spacetimedb instance. @@ -456,7 +456,7 @@ private void OnMessageProcessComplete(Message message, IList events) { if (events[i].table.InsertCallback != null) { - events[i].table.InsertCallback.Invoke(null, new[] { newValue }); + events[i].table.InsertCallback.Invoke(newValue, message.Event); } } catch (Exception e) @@ -469,7 +469,7 @@ private void OnMessageProcessComplete(Message message, IList events) if (events[i].table.RowUpdatedCallback != null) { events[i].table.RowUpdatedCallback - .Invoke(null, new[] { tableOp, null, newValue }); + .Invoke(tableOp, null, newValue, message.Event); } } catch (Exception e) @@ -492,7 +492,7 @@ private void OnMessageProcessComplete(Message message, IList events) { try { - events[i].table.DeleteCallback.Invoke(null, new[] { oldValue }); + events[i].table.DeleteCallback.Invoke(oldValue, message.Event); } catch (Exception e) { @@ -505,7 +505,7 @@ private void OnMessageProcessComplete(Message message, IList events) try { events[i].table.RowUpdatedCallback - .Invoke(null, new[] { tableOp, oldValue, null }); + .Invoke(tableOp, oldValue, null, message.Event); } catch (Exception e) { @@ -528,7 +528,7 @@ private void OnMessageProcessComplete(Message message, IList events) { if (events[i].table.UpdateCallback != null) { - events[i].table.UpdateCallback.Invoke(null, new[] { oldValue, newValue }); + events[i].table.UpdateCallback.Invoke(oldValue, newValue, message.Event); } } catch (Exception e) @@ -541,7 +541,7 @@ private void OnMessageProcessComplete(Message message, IList events) if (events[i].table.RowUpdatedCallback != null) { events[i].table.RowUpdatedCallback - .Invoke(null, new[] { tableOp, oldValue, null }); + .Invoke(tableOp, oldValue, null, message.Event); } } catch (Exception e) @@ -560,7 +560,7 @@ private void OnMessageProcessComplete(Message message, IList events) throw new ArgumentOutOfRangeException(); } - onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue); + onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue, message.Event); } switch (message.TypeCase) From 2a6e0372963a45c8523dee664e1bedd99d7273d2 Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Tue, 13 Jun 2023 15:07:18 -0400 Subject: [PATCH 028/223] Fix compile error in sdk (#22) Co-authored-by: Derek Brinkmann --- sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 620b7271e04..2e0560e5b10 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -180,7 +180,7 @@ struct ProcessedMessage public IList events; } - private readonly BlockingCollection _messageQueue = new(new ConcurrentQueue()); + private readonly BlockingCollection _messageQueue = new BlockingCollection(new ConcurrentQueue()); private ProcessedMessage? nextMessage; void ProcessMessages() From b1b96898b7ec0b85e44bd53749fccebc385dcdcb Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Wed, 14 Jun 2023 11:11:22 -0400 Subject: [PATCH 029/223] Add onSubscriptionUpdate callback (#21) * Add onSubscriptionUpdate callback * Remove unnecesary onTransactionComplete --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 2e0560e5b10..2282204fc66 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -79,9 +79,9 @@ private struct DbEvent public event RowUpdate onRowUpdate; /// - /// Callback is invoked after a transaction or subscription update is received and all updates have been applied. + /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. /// - public event Action onTransactionComplete; + public event Action onSubscriptionUpdate; /// /// Called when we receive an identity from the server @@ -566,10 +566,9 @@ private void OnMessageProcessComplete(Message message, IList events) switch (message.TypeCase) { case Message.TypeOneofCase.SubscriptionUpdate: - onTransactionComplete?.Invoke(); + onSubscriptionUpdate?.Invoke(); break; case Message.TypeOneofCase.TransactionUpdate: - onTransactionComplete?.Invoke(); onEvent?.Invoke(message.TransactionUpdate.Event); var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; From 91b3e23f323a23dc749912d1d75406e9c56e3e13 Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Wed, 14 Jun 2023 12:13:03 -0300 Subject: [PATCH 030/223] Deserializing reducer args before table updates so they can be accessed from callbacks (#20) Co-authored-by: Steve --- .../Scripts/ClientApiExtensions.cs | 8 ++++++++ .../Scripts/ClientApiExtensions.cs.meta | 11 +++++++++++ .../SpacetimeDB/Scripts/NetworkManager.cs | 19 +++++++++++++------ 3 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs new file mode 100644 index 00000000000..23cecde2f18 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs @@ -0,0 +1,8 @@ + +namespace ClientApi +{ + public partial class FunctionCall + { + public object[] ReducerArguments { get; internal set; } + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs.meta new file mode 100644 index 00000000000..d0b7169a59d --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22f2002d28671854b9e0e1f263d3fcb8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 2282204fc66..56115a88c40 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -96,8 +96,8 @@ private struct DbEvent private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; public static ClientCache clientDB; - public static Dictionary reducerEventCache = new Dictionary(); - public static Dictionary deserializeEventCache = new Dictionary(); + public static Dictionary> reducerEventCache = new Dictionary>(); + public static Dictionary> deserializeEventCache = new Dictionary>(); private Thread messageProcessThread; @@ -160,13 +160,13 @@ protected void Awake() if (methodInfo.GetCustomAttribute() is { } reducerEvent) { - reducerEventCache.Add(reducerEvent.FunctionName, methodInfo); + reducerEventCache.Add(reducerEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); } if (methodInfo.GetCustomAttribute() is { } deserializeEvent) { - deserializeEventCache.Add(deserializeEvent.FunctionName, methodInfo); + deserializeEventCache.Add(deserializeEvent.FunctionName, (Func)methodInfo.CreateDelegate(typeof(Func))); } } @@ -367,6 +367,13 @@ void ProcessMessages() } } + + if (message.TypeCase == Message.TypeOneofCase.TransactionUpdate && + deserializeEventCache.TryGetValue(message.TransactionUpdate.Event.FunctionCall.Reducer, out var deserializer)) + { + message.TransactionUpdate.Event.FunctionCall.ReducerArguments = deserializer.Invoke(message.TransactionUpdate.Event); + } + return (message, dbEvents); } } @@ -574,7 +581,7 @@ private void OnMessageProcessComplete(Message message, IList events) var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; if (reducerEventCache.TryGetValue(functionName, out var value)) { - value.Invoke(null, new object[] { message.TransactionUpdate.Event }); + value.Invoke(message.TransactionUpdate.Event); } break; @@ -635,4 +642,4 @@ private void Update() } } } -} +} \ No newline at end of file From e806ee3dbf392ae9ac43ff668435819acba20e7d Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Thu, 15 Jun 2023 13:04:17 -0300 Subject: [PATCH 031/223] Reducer args in table updates 2 (#23) * Deserializing reducer args before table updates so they can be accessed from callbacks * Reducer arguments in table events * Removed redundant onSubscriptionUpdate --------- Co-authored-by: Steve Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> Co-authored-by: John Detter --- .../SpacetimeDB/Scripts/ClientApiExtensions.cs | 5 ++--- .../Assets/SpacetimeDB/Scripts/NetworkManager.cs | 16 ++++++++-------- .../Scripts/ReducerMismatchException.cs | 16 ++++++++++++++++ .../Scripts/ReducerMismatchException.cs.meta | 11 +++++++++++ .../SpacetimeDB/Scripts/{Reducer.cs => Stubs.cs} | 7 ++++++- .../Scripts/{Reducer.cs.meta => Stubs.cs.meta} | 0 6 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs.meta rename sdks/csharp/Assets/SpacetimeDB/Scripts/{Reducer.cs => Stubs.cs} (51%) rename sdks/csharp/Assets/SpacetimeDB/Scripts/{Reducer.cs.meta => Stubs.cs.meta} (100%) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs index 23cecde2f18..005613b792d 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs @@ -1,8 +1,7 @@ - -namespace ClientApi +namespace ClientApi { public partial class FunctionCall { - public object[] ReducerArguments { get; internal set; } + public SpacetimeDB.ReducerCallInfo CallInfo { get; internal set; } } } \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 56115a88c40..af60d04387e 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -41,7 +41,7 @@ public class SubscriptionRequest public string subscriptionQuery; } - private struct DbEvent + public struct DbEvent { public ClientCache.TableCache table; public TableOp op; @@ -51,7 +51,7 @@ private struct DbEvent public byte[] insertedPk; } - public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, ClientApi.Event dbEvent); + public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, SpacetimeDB.ReducerCallInfo dbEvent); /// /// Called when a connection is established to a spacetimedb instance. @@ -97,7 +97,7 @@ private struct DbEvent private bool connectionClosed; public static ClientCache clientDB; public static Dictionary> reducerEventCache = new Dictionary>(); - public static Dictionary> deserializeEventCache = new Dictionary>(); + public static Dictionary> deserializeEventCache = new Dictionary>(); private Thread messageProcessThread; @@ -166,7 +166,7 @@ protected void Awake() if (methodInfo.GetCustomAttribute() is { } deserializeEvent) { - deserializeEventCache.Add(deserializeEvent.FunctionName, (Func)methodInfo.CreateDelegate(typeof(Func))); + deserializeEventCache.Add(deserializeEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); } } @@ -371,7 +371,7 @@ void ProcessMessages() if (message.TypeCase == Message.TypeOneofCase.TransactionUpdate && deserializeEventCache.TryGetValue(message.TransactionUpdate.Event.FunctionCall.Reducer, out var deserializer)) { - message.TransactionUpdate.Event.FunctionCall.ReducerArguments = deserializer.Invoke(message.TransactionUpdate.Event); + deserializer.Invoke(message.TransactionUpdate.Event); } return (message, dbEvents); @@ -444,7 +444,7 @@ private void OnMessageProcessComplete(Message message, IList events) throw new ArgumentOutOfRangeException(); } } - + // Send out events var eventCount = events.Count; for (var i = 0; i < eventCount; i++) @@ -567,7 +567,7 @@ private void OnMessageProcessComplete(Message message, IList events) throw new ArgumentOutOfRangeException(); } - onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue, message.Event); + onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue, message.Event?.FunctionCall.CallInfo); } switch (message.TypeCase) @@ -642,4 +642,4 @@ private void Update() } } } -} \ No newline at end of file +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs new file mode 100644 index 00000000000..bf36126479e --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SpacetimeDB +{ + class ReducerMismatchException : Exception + { + public ReducerMismatchException(string originalReducerName, string attemptedConversionReducerName) + : base($"Cannot cast agruments from {originalReducerName} reducer call into {attemptedConversionReducerName} reducer arguments") + { + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs.meta new file mode 100644 index 00000000000..a3953c5199a --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e821d7739e1cf0f408fe82f799c934cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs similarity index 51% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs rename to sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs index 52f83947c98..f799ca317ab 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs @@ -7,4 +7,9 @@ namespace SpacetimeDB public partial class Reducer { } -} + + public partial class ReducerCallInfo + { + public SpacetimeDB.NetworkManager.DbEvent[] RowChanges { get; internal set; } + } +} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/Reducer.cs.meta rename to sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta From 7737b9882b0861db80760c37a867645ede97df29 Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Thu, 15 Jun 2023 13:26:59 -0300 Subject: [PATCH 032/223] Changed guid (#25) Co-authored-by: Steve --- sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta index 7f8d4251241..47e935379be 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3c5f8f3b1a67eaf268e00840da8aa4bd +guid: 3c5f8f3b1a67eaf268e00840da8aa4be MonoImporter: externalObjects: {} serializedVersion: 2 From cf9c5b02e43d4f0844ef1e74db81313359908c54 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 15 Jun 2023 15:05:54 -0500 Subject: [PATCH 033/223] Fixed API (#26) Co-authored-by: John Detter --- sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs index 77dfe106a21..2d616f4c5c4 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs @@ -142,7 +142,7 @@ public WebSocket(ConnectOptions options) public async Task Connect(string auth, string host, string nameOrAddress, bool sslEnabled) { var protocol = sslEnabled ? "wss" : "ws"; - var url = new Uri($"{protocol}://{host}/database/subscribe?name_or_address={nameOrAddress}"); + var url = new Uri($"{protocol}://{host}/database/subscribe/{nameOrAddress}"); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000); From 93827106cf121aae4763268cff12f49c627ef86d Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Fri, 16 Jun 2023 11:28:17 -0300 Subject: [PATCH 034/223] Reducer event (#28) * Deserializing reducer args before table updates so they can be accessed from callbacks * Reducer arguments in table events * Adding OnBeforeDelete event to tables * Renaming ReducerCallInfo to ReducerEvent * Removed extra onSubscriptionUpdate --------- Co-authored-by: Steve Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> --- .../Scripts/ClientApiExtensions.cs | 2 +- .../Assets/SpacetimeDB/Scripts/ClientCache.cs | 19 +++++++++++++++ .../SpacetimeDB/Scripts/NetworkManager.cs | 24 ++++++++++++++++--- .../SpacetimeDB/Scripts/ReducerExtensions.cs | 4 ++-- .../Assets/SpacetimeDB/Scripts/Stubs.cs | 3 +-- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs index 005613b792d..770bc9727df 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs @@ -2,6 +2,6 @@ { public partial class FunctionCall { - public SpacetimeDB.ReducerCallInfo CallInfo { get; internal set; } + public SpacetimeDB.ReducerEvent CallInfo { get; internal set; } } } \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index 72b83ebb459..a39299ccf5c 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -55,6 +55,7 @@ public Type ClientTableType } public Action InsertCallback; + public Action BeforeDeleteCallback; public Action DeleteCallback; public Action UpdateCallback; // TODO: Consider renaming this one, this kind of implies that its a callback for the Update operation @@ -79,6 +80,7 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func)clientTableType.GetMethod("OnInsertEvent")?.CreateDelegate(typeof(Action)); + BeforeDeleteCallback = (Action)clientTableType.GetMethod("OnBeforeDeleteEvent")?.CreateDelegate(typeof(Action)); DeleteCallback = (Action)clientTableType.GetMethod("OnDeleteEvent")?.CreateDelegate(typeof(Action)); UpdateCallback = (Action)clientTableType.GetMethod("OnUpdateEvent")?.CreateDelegate(typeof(Action)); RowUpdatedCallback = (Action)clientTableType.GetMethod("OnRowUpdateEvent") @@ -185,6 +187,23 @@ public object DeleteEntry(byte[] rowPk) return null; } + /// + /// Gets a value from the table + /// + /// The primary key that uniquely identifies this row + /// + public bool TryGetValue(byte[] rowPk, out object value) + { + if (entries.TryGetValue(rowPk, out var v)) + { + value = v.Item2; + return true; + } + + value = null; + return false; + } + public bool ComparePrimaryKey(AlgebraicValue v1, AlgebraicValue v2) { return (bool)ComparePrimaryKeyFunc.Invoke(rowSchema, v1, v2); diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index af60d04387e..4c4df016f2e 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -157,13 +157,13 @@ protected void Awake() // cache all our reducer events by their function name foreach (var methodInfo in typeof(SpacetimeDB.Reducer).GetMethods()) { - if (methodInfo.GetCustomAttribute() is + if (methodInfo.GetCustomAttribute() is { } reducerEvent) { reducerEventCache.Add(reducerEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); } - if (methodInfo.GetCustomAttribute() is + if (methodInfo.GetCustomAttribute() is { } deserializeEvent) { deserializeEventCache.Add(deserializeEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); @@ -420,7 +420,25 @@ private void OnMessageProcessComplete(Message message, IList events) { case Message.TypeOneofCase.SubscriptionUpdate: case Message.TypeOneofCase.TransactionUpdate: - // First apply all of the state + // First trigger OnBeforeDelete + for (var i = 0; i < events.Count; i++) + { + // TODO: Reimplement updates when we add support for primary keys + var ev = events[i]; + if (ev.op == TableOp.Delete && ev.table.TryGetValue(ev.deletedPk, out var oldVal)) + { + try + { + ev.table.BeforeDeleteCallback?.Invoke(oldVal, message.Event); + } + catch (Exception e) + { + Debug.LogException(e); + } + } + } + + // Apply all of the state for (var i = 0; i < events.Count; i++) { // TODO: Reimplement updates when we add support for primary keys diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs index 0709153d6c6..cca7f2849dd 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs @@ -2,12 +2,12 @@ namespace SpacetimeDB { - public class ReducerEvent : Attribute + public class ReducerCallbackAttribute : Attribute { public string FunctionName { get; set; } } - public class DeserializeEvent : Attribute + public class DeserializeEventAttribute : Attribute { public string FunctionName { get; set; } } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs index f799ca317ab..316a9869776 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs @@ -8,8 +8,7 @@ public partial class Reducer { } - public partial class ReducerCallInfo + public partial class ReducerEvent { - public SpacetimeDB.NetworkManager.DbEvent[] RowChanges { get; internal set; } } } \ No newline at end of file From 85b8020398684ccc031777344525098835a8736e Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Fri, 16 Jun 2023 11:32:47 -0300 Subject: [PATCH 035/223] On before delete (#24) * Deserializing reducer args before table updates so they can be accessed from callbacks * Reducer arguments in table events * Adding OnBeforeDelete event to tables --------- Co-authored-by: Steve Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> --- sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 4c4df016f2e..eff79c1a20a 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -83,6 +83,11 @@ public struct DbEvent /// public event Action onSubscriptionUpdate; + /// + /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. + /// + public event Action onSubscriptionUpdate; + /// /// Called when we receive an identity from the server /// From 31dedc3229308cca41669c39c8c36ddbf42bf5bd Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Fri, 16 Jun 2023 12:09:32 -0500 Subject: [PATCH 036/223] Renamed onSubscriptionUpdate to onSubscriptionApplied (#27) Co-authored-by: John Detter --- sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index eff79c1a20a..36e55dced12 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -81,7 +81,7 @@ public struct DbEvent /// /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. /// - public event Action onSubscriptionUpdate; + public event Action onSubscriptionApplied; /// /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. @@ -596,7 +596,7 @@ private void OnMessageProcessComplete(Message message, IList events) switch (message.TypeCase) { case Message.TypeOneofCase.SubscriptionUpdate: - onSubscriptionUpdate?.Invoke(); + onSubscriptionApplied?.Invoke(); break; case Message.TypeOneofCase.TransactionUpdate: onEvent?.Invoke(message.TransactionUpdate.Event); From 351616e9807de8f58576aabc5303ae1af6673921 Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Mon, 19 Jun 2023 20:34:48 -0300 Subject: [PATCH 037/223] Fixed occasional double insert (#30) Co-authored-by: Steve --- .../Assets/SpacetimeDB/Scripts/NetworkManager.cs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 36e55dced12..f253e386ec9 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -252,22 +252,6 @@ void ProcessMessages() switch (row.Op) { case TableRowOperation.Types.OperationType.Delete: - // If we don't already have this row, we should skip this delete - if (!table.entries.ContainsKey(rowPk)) - { - if (update.TableRowOperations.Any( - a => a.RowPk.ToByteArray().SequenceEqual(rowPk))) - { - // Debug.LogWarning("We are deleting and inserting the same row in the same TX!"); - } - else - { - Debug.LogWarning( - $"We received a delete for a row we don't even subscribe to! table={table.Name}"); - } - continue; - } - dbEvents.Add(new DbEvent { table = table, From 4fb197506b2c67c51b5bb642d6f6d8c23f0844ac Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Mon, 19 Jun 2023 20:36:22 -0300 Subject: [PATCH 038/223] Supporting multiple messages per frame (#29) Co-authored-by: Steve --- .../SpacetimeDB/Scripts/NetworkManager.cs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index f253e386ec9..23360b1f01e 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -186,25 +186,21 @@ struct ProcessedMessage } private readonly BlockingCollection _messageQueue = new BlockingCollection(new ConcurrentQueue()); - private ProcessedMessage? nextMessage; + private readonly BlockingCollection _nextMessageQueue = new BlockingCollection(new ConcurrentQueue()); void ProcessMessages() { while (true) { var bytes = _messageQueue.Take(); - // Wait for the main thread to consume the message we digested for them - while (nextMessage.HasValue) - { - Thread.Sleep(1); - } var (m, events) = PreProcessMessage(bytes); - nextMessage = new ProcessedMessage + var processedMessage = new ProcessedMessage { message = m, events = events, }; + _nextMessageQueue.Add(processedMessage); } (Message, List) PreProcessMessage(byte[] bytes) @@ -642,11 +638,10 @@ private void Update() { webSocket.Update(); - if (nextMessage != null) + while (_nextMessageQueue.TryTake(out var nextMessage)) { - OnMessageProcessComplete(nextMessage.Value.message, nextMessage.Value.events); - nextMessage = null; + OnMessageProcessComplete(nextMessage.message, nextMessage.events); } } } -} +} \ No newline at end of file From 8a74cfdc1e2ba0bf3a27c7f8869e5191880363f0 Mon Sep 17 00:00:00 2001 From: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Date: Mon, 26 Jun 2023 18:10:19 -0300 Subject: [PATCH 039/223] Custom indexes (#32) * OnUnhandledReducerError * Fixed Bitcraft namespace * Adding support for custom indexes in tables * Deduped ByteArrayComparer * Removed onUnhandledReducerError --------- Co-authored-by: Steve --- .../Assets/SpacetimeDB/Scripts/ClientCache.cs | 24 ++-------- .../SpacetimeDB/Scripts/NetworkManager.cs | 23 ++++++---- .../Assets/SpacetimeDB/Scripts/Utils.cs | 44 +++++++++++++++++++ .../Assets/SpacetimeDB/Scripts/Utils.cs.meta | 11 +++++ 4 files changed, 73 insertions(+), 29 deletions(-) create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs create mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs.meta diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs index a39299ccf5c..bd7ad2b2db8 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs @@ -16,26 +16,6 @@ public class ClientCache { public class TableCache { - public class ByteArrayComparer : IEqualityComparer - { - public bool Equals(byte[] left, byte[] right) - { - if (left == null || right == null) - { - return left == right; - } - - return left.SequenceEqual(right); - } - - public int GetHashCode(byte[] key) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); - return key.Sum(b => b); - } - } - private readonly string name; private readonly Type clientTableType; private readonly AlgebraicType rowSchema; @@ -54,6 +34,8 @@ public Type ClientTableType get => clientTableType; } + public Action InternalValueInsertedCallback; + public Action InternalValueDeletedCallback; public Action InsertCallback; public Action BeforeDeleteCallback; public Action DeleteCallback; @@ -79,6 +61,8 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func)clientTableType.GetMethod("InternalOnValueInserted", BindingFlags.NonPublic | BindingFlags.Static)?.CreateDelegate(typeof(Action)); + InternalValueDeletedCallback = (Action)clientTableType.GetMethod("InternalOnValueDeleted", BindingFlags.NonPublic | BindingFlags.Static)?.CreateDelegate(typeof(Action)); InsertCallback = (Action)clientTableType.GetMethod("OnInsertEvent")?.CreateDelegate(typeof(Action)); BeforeDeleteCallback = (Action)clientTableType.GetMethod("OnBeforeDeleteEvent")?.CreateDelegate(typeof(Action)); DeleteCallback = (Action)clientTableType.GetMethod("OnDeleteEvent")?.CreateDelegate(typeof(Action)); diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs index 23360b1f01e..ca00f30384b 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs @@ -17,7 +17,7 @@ using SpacetimeDB.SATS; using UnityEngine; using UnityEngine.Rendering; -using Event = ClientApi.Event; +using ReducerEvent = SpacetimeDB.ReducerEvent; namespace SpacetimeDB { @@ -83,11 +83,6 @@ public struct DbEvent /// public event Action onSubscriptionApplied; - /// - /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. - /// - public event Action onSubscriptionUpdate; - /// /// Called when we receive an identity from the server /// @@ -101,7 +96,7 @@ public struct DbEvent private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; public static ClientCache clientDB; - public static Dictionary> reducerEventCache = new Dictionary>(); + public static Dictionary> reducerEventCache = new Dictionary>(); public static Dictionary> deserializeEventCache = new Dictionary>(); private Thread messageProcessThread; @@ -165,7 +160,7 @@ protected void Awake() if (methodInfo.GetCustomAttribute() is { } reducerEvent) { - reducerEventCache.Add(reducerEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); + reducerEventCache.Add(reducerEvent.FunctionName, (Func)methodInfo.CreateDelegate(typeof(Func))); } if (methodInfo.GetCustomAttribute() is @@ -340,7 +335,7 @@ void ProcessMessages() .Where(a => a.Op == TableRowOperation.Types.OperationType.Insert) .Select(b => b.RowPk.ToByteArray()); var existingPks = clientTable.entries.Select(a => a.Key); - dbEvents.AddRange(existingPks.Except(newPks, new ClientCache.TableCache.ByteArrayComparer()) + dbEvents.AddRange(existingPks.Except(newPks, new ByteArrayComparer()) .Select(a => new DbEvent { deletedPk = a, @@ -432,15 +427,25 @@ private void OnMessageProcessComplete(Message message, IList events) { case TableOp.Delete: ev.oldValue = events[i].table.DeleteEntry(ev.deletedPk); + if (ev.oldValue != null) + { + ev.table.InternalValueDeletedCallback(ev.oldValue); + } events[i] = ev; break; case TableOp.Insert: ev.newValue = events[i].table.InsertEntry(ev.insertedPk); + ev.table.InternalValueInsertedCallback(ev.newValue); events[i] = ev; break; case TableOp.Update: ev.oldValue = events[i].table.DeleteEntry(ev.deletedPk); ev.newValue = events[i].table.InsertEntry(ev.insertedPk); + if (ev.oldValue != null) + { + ev.table.InternalValueDeletedCallback(ev.oldValue); + } + ev.table.InternalValueInsertedCallback(ev.newValue); events[i] = ev; break; default: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs new file mode 100644 index 00000000000..513db490b79 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SpacetimeDB +{ + public static class Utils + { + public static bool ByteArrayCompare(byte[] a1, byte[] a2) + { + if (a1 == null || a2 == null) + return a1 == a2; + + if (a1.Length != a2.Length) + return false; + + for (int i = 0; i < a1.Length; i++) + if (a1[i] != a2[i]) + return false; + + return true; + } + } + + public class ByteArrayComparer : IEqualityComparer + { + public bool Equals(byte[] x, byte[] y) + { + return Utils.ByteArrayCompare(x, y); + } + + public int GetHashCode(byte[] obj) + { + if (obj == null) + return 0; + int sum = 0; + for (int i = 0; i < obj.Length; i++) + sum += obj[i]; + return sum; + } + } +} diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs.meta new file mode 100644 index 00000000000..23a54bdf401 --- /dev/null +++ b/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e446381d1ca09c249ba226d1e6edbfc8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 0a46b0118e67fb2acbf2c50961dd243affdeb112 Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Fri, 30 Jun 2023 16:11:32 -0400 Subject: [PATCH 040/223] Convert Unity SDK into a CSharp SDK with Unity support (#34) * Initial CSharp SDK Commit * Compile error fixes * Minor fixes --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/.gitignore | 192 +- sdks/csharp/Assets/ExportPackage.cs | 12 - sdks/csharp/Assets/ExportPackage.cs.meta | 11 - sdks/csharp/Assets/Main.unity | 301 - sdks/csharp/Assets/Main.unity.meta | 7 - sdks/csharp/Assets/Materials.meta | 8 - sdks/csharp/Assets/Materials/Skybox_Mat.mat | 89 - .../Assets/Materials/Skybox_Mat.mat.meta | 8 - sdks/csharp/Assets/Presets.meta | 8 - .../Presets/AudioCompressedInMemory.preset | 137 - .../AudioCompressedInMemory.preset.meta | 8 - .../Assets/Presets/AudioStreaming.preset | 137 - .../Assets/Presets/AudioStreaming.preset.meta | 8 - sdks/csharp/Assets/Presets/Defaults.meta | 8 - .../Defaults/AlbedoTexture_Default.preset | 497 - .../AlbedoTexture_Default.preset.meta | 8 - .../Defaults/AudioDecompressOnLoad.preset | 137 - .../AudioDecompressOnLoad.preset.meta | 8 - .../Defaults/DirectionalLight_Default.preset | 137 - .../DirectionalLight_Default.preset.meta | 8 - .../Assets/Presets/NormalTexture.preset | 497 - .../Assets/Presets/NormalTexture.preset.meta | 8 - .../Assets/Presets/UtilityTexture.preset | 497 - .../Assets/Presets/UtilityTexture.preset.meta | 8 - sdks/csharp/Assets/Settings.meta | 8 - .../Assets/Settings/ForwardRenderer.asset | 36 - .../Settings/ForwardRenderer.asset.meta | 8 - .../Assets/Settings/SampleSceneProfile.asset | 118 - .../Settings/SampleSceneProfile.asset.meta | 8 - .../Settings/UniversalRP-HighQuality.asset | 53 - .../UniversalRP-HighQuality.asset.meta | 8 - .../Settings/UniversalRP-LowQuality.asset | 53 - .../UniversalRP-LowQuality.asset.meta | 8 - .../Settings/UniversalRP-MediumQuality.asset | 53 - .../UniversalRP-MediumQuality.asset.meta | 8 - sdks/csharp/Assets/SpacetimeDB.meta | 8 - sdks/csharp/Assets/SpacetimeDB/Packages.meta | 8 - .../Packages/Google.Protobuf.3.21.9.meta | 8 - .../Google.Protobuf.3.21.9.nupkg | Bin 1208111 -> 0 bytes .../Google.Protobuf.3.21.9.nupkg.meta | 7 - .../Packages/Google.Protobuf.3.21.9/lib.meta | 8 - .../Google.Protobuf.3.21.9/lib/net45.meta | 8 - .../lib/net45/Google.Protobuf.dll | Bin 410904 -> 0 bytes .../lib/net45/Google.Protobuf.dll.meta | 33 - .../lib/net45/Google.Protobuf.xml | 10465 ---------------- .../lib/net45/Google.Protobuf.xml.meta | 7 - .../Packages/System.Buffers.4.4.0.meta | 8 - .../Packages/System.Buffers.4.4.0/LICENSE.TXT | 23 - .../System.Buffers.4.4.0/LICENSE.TXT.meta | 7 - .../System.Buffers.4.4.0.nupkg | Bin 78363 -> 0 bytes .../System.Buffers.4.4.0.nupkg.meta | 7 - .../THIRD-PARTY-NOTICES.TXT | 226 - .../THIRD-PARTY-NOTICES.TXT.meta | 7 - .../Packages/System.Buffers.4.4.0/lib.meta | 8 - .../lib/netstandard2.0.meta | 8 - .../lib/netstandard2.0/System.Buffers.dll | Bin 27992 -> 0 bytes .../netstandard2.0/System.Buffers.dll.meta | 33 - .../lib/netstandard2.0/System.Buffers.xml | 39 - .../netstandard2.0/System.Buffers.xml.meta | 7 - .../useSharedDesignerContext.txt | 0 .../useSharedDesignerContext.txt.meta | 7 - .../Packages/System.Buffers.4.4.0/version.txt | 1 - .../System.Buffers.4.4.0/version.txt.meta | 7 - .../Packages/System.Memory.4.5.3.meta | 8 - .../Packages/System.Memory.4.5.3/LICENSE.TXT | 23 - .../System.Memory.4.5.3/LICENSE.TXT.meta | 7 - .../System.Memory.4.5.3.nupkg | Bin 154054 -> 0 bytes .../System.Memory.4.5.3.nupkg.meta | 7 - .../THIRD-PARTY-NOTICES.TXT | 309 - .../THIRD-PARTY-NOTICES.TXT.meta | 7 - .../Packages/System.Memory.4.5.3/lib.meta | 8 - .../lib/netstandard2.0.meta | 8 - .../lib/netstandard2.0/System.Memory.dll | Bin 148760 -> 0 bytes .../lib/netstandard2.0/System.Memory.dll.meta | 33 - .../lib/netstandard2.0/System.Memory.xml | 355 - .../lib/netstandard2.0/System.Memory.xml.meta | 7 - .../useSharedDesignerContext.txt | 0 .../useSharedDesignerContext.txt.meta | 7 - .../Packages/System.Memory.4.5.3/version.txt | 1 - .../System.Memory.4.5.3/version.txt.meta | 7 - ...Runtime.CompilerServices.Unsafe.4.5.2.meta | 8 - .../LICENSE.TXT | 23 - .../LICENSE.TXT.meta | 7 - ...untime.CompilerServices.Unsafe.4.5.2.nupkg | Bin 104723 -> 0 bytes ...e.CompilerServices.Unsafe.4.5.2.nupkg.meta | 7 - .../THIRD-PARTY-NOTICES.TXT | 309 - .../THIRD-PARTY-NOTICES.TXT.meta | 7 - .../lib.meta | 8 - .../lib/netstandard2.0.meta | 8 - ...System.Runtime.CompilerServices.Unsafe.dll | Bin 23600 -> 0 bytes ...m.Runtime.CompilerServices.Unsafe.dll.meta | 33 - ...System.Runtime.CompilerServices.Unsafe.xml | 200 - ...m.Runtime.CompilerServices.Unsafe.xml.meta | 7 - .../useSharedDesignerContext.txt | 0 .../useSharedDesignerContext.txt.meta | 7 - .../version.txt | 1 - .../version.txt.meta | 7 - sdks/csharp/Assets/SpacetimeDB/Scripts.meta | 8 - .../Scripts/ByteArrayConverter.cs.meta | 11 - .../SpacetimeDB/Scripts/ClientApi.cs.meta | 11 - .../Scripts/ClientApiExtensions.cs.meta | 11 - .../SpacetimeDB/Scripts/ClientCache.cs.meta | 3 - .../Scripts/IDatabaseTable.cs.meta | 11 - .../SpacetimeDB/Scripts/Identity.cs.meta | 11 - .../Scripts/NetworkManager.cs.meta | 11 - .../Scripts/ReducerExtensions.cs.meta | 11 - .../Scripts/ReducerMismatchException.cs.meta | 11 - .../Assets/SpacetimeDB/Scripts/SATS.meta | 3 - .../Scripts/SATS/AlgebraicType.cs.meta | 3 - .../Scripts/SATS/AlgebraicValue.cs.meta | 11 - .../Scripts/SATS/Typespace.cs.meta | 11 - .../Assets/SpacetimeDB/Scripts/Stubs.cs | 14 - .../Assets/SpacetimeDB/Scripts/Stubs.cs.meta | 11 - .../Assets/SpacetimeDB/Scripts/Utils.cs.meta | 11 - .../SpacetimeDB/Scripts/WebSocket.cs.meta | 3 - .../Assets/SpacetimeDB/Scripts/json.meta | 3 - .../Scripts/json/EnumAttribute.cs.meta | 11 - .../Scripts/json/EnumWrapper.cs.meta | 11 - .../Scripts/json/EnumWrapperConverter.cs.meta | 11 - .../Scripts/json/JsonContractResolver.cs.meta | 11 - .../Scripts/json/SomeAttribute.cs.meta | 11 - .../Scripts/json/SomeWrapper.cs.meta | 11 - .../Scripts/json/SomeWrapperConverter.cs.meta | 3 - sdks/csharp/Packages/manifest.json | 44 - sdks/csharp/Packages/packages-lock.json | 403 - .../csharp/ProjectSettings/AudioManager.asset | 19 - .../ProjectSettings/ClusterInputManager.asset | 6 - .../ProjectSettings/DynamicsManager.asset | 36 - .../ProjectSettings/EditorBuildSettings.asset | 11 - .../ProjectSettings/EditorSettings.asset | 31 - .../ProjectSettings/GraphicsSettings.asset | 68 - .../csharp/ProjectSettings/InputManager.asset | 487 - .../csharp/ProjectSettings/NavMeshAreas.asset | 91 - .../PackageManagerSettings.asset | 43 - .../ProjectSettings/Physics2DSettings.asset | 56 - .../ProjectSettings/PresetManager.asset | 27 - .../ProjectSettings/ProjectSettings.asset | 698 -- .../csharp/ProjectSettings/ProjectVersion.txt | 2 - .../ProjectSettings/QualitySettings.asset | 128 - .../SceneTemplateSettings.json | 167 - sdks/csharp/ProjectSettings/TagManager.asset | 43 - sdks/csharp/ProjectSettings/TimeManager.asset | 9 - .../ProjectSettings/URPProjectSettings.asset | 15 - .../UnityConnectSettings.asset | 35 - sdks/csharp/ProjectSettings/VFXManager.asset | 11 - .../VersionControlSettings.asset | 8 - sdks/csharp/ProjectSettings/XRSettings.asset | 10 - sdks/csharp/SpacetimeDBCSharpSDK.csproj | 14 + sdks/csharp/export.sh | 21 - .../Scripts => src}/ByteArrayConverter.cs | 0 .../SpacetimeDB/Scripts => src}/ClientApi.cs | 0 .../Scripts => src}/ClientApiExtensions.cs | 2 +- .../Scripts => src}/ClientCache.cs | 41 +- sdks/csharp/src/ConsoleLogger.cs | 60 + .../Scripts => src}/IDatabaseTable.cs | 1 - sdks/csharp/src/ILogger.cs | 19 + .../SpacetimeDB/Scripts => src}/Identity.cs | 1 - sdks/csharp/src/NetworkManager.cs | 51 + .../Scripts => src}/ReducerExtensions.cs | 0 .../ReducerMismatchException.cs | 2 +- .../Scripts => src}/SATS/AlgebraicType.cs | 0 .../Scripts => src}/SATS/AlgebraicValue.cs | 0 .../Scripts => src}/SATS/Typespace.cs | 2 - .../SpacetimeDBClient.cs} | 143 +- sdks/csharp/src/Stubs.cs | 25 + sdks/csharp/src/UnityDebugLogger.cs | 34 + .../SpacetimeDB/Scripts => src}/Utils.cs | 0 .../SpacetimeDB/Scripts => src}/WebSocket.cs | 14 +- .../Scripts => src}/json/EnumAttribute.cs | 1 - .../Scripts => src}/json/EnumWrapper.cs | 1 - .../json/EnumWrapperConverter.cs | 1 - .../json/JsonContractResolver.cs | 6 +- .../Scripts => src}/json/SomeAttribute.cs | 1 - .../Scripts => src}/json/SomeWrapper.cs | 1 - .../json/SomeWrapperConverter.cs | 0 sdks/csharp/upload.sh | 30 - 176 files changed, 446 insertions(+), 18170 deletions(-) delete mode 100644 sdks/csharp/Assets/ExportPackage.cs delete mode 100644 sdks/csharp/Assets/ExportPackage.cs.meta delete mode 100644 sdks/csharp/Assets/Main.unity delete mode 100644 sdks/csharp/Assets/Main.unity.meta delete mode 100644 sdks/csharp/Assets/Materials.meta delete mode 100644 sdks/csharp/Assets/Materials/Skybox_Mat.mat delete mode 100644 sdks/csharp/Assets/Materials/Skybox_Mat.mat.meta delete mode 100644 sdks/csharp/Assets/Presets.meta delete mode 100644 sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset delete mode 100644 sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset.meta delete mode 100644 sdks/csharp/Assets/Presets/AudioStreaming.preset delete mode 100644 sdks/csharp/Assets/Presets/AudioStreaming.preset.meta delete mode 100644 sdks/csharp/Assets/Presets/Defaults.meta delete mode 100644 sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset delete mode 100644 sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset.meta delete mode 100644 sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset delete mode 100644 sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset.meta delete mode 100644 sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset delete mode 100644 sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset.meta delete mode 100644 sdks/csharp/Assets/Presets/NormalTexture.preset delete mode 100644 sdks/csharp/Assets/Presets/NormalTexture.preset.meta delete mode 100644 sdks/csharp/Assets/Presets/UtilityTexture.preset delete mode 100644 sdks/csharp/Assets/Presets/UtilityTexture.preset.meta delete mode 100644 sdks/csharp/Assets/Settings.meta delete mode 100644 sdks/csharp/Assets/Settings/ForwardRenderer.asset delete mode 100644 sdks/csharp/Assets/Settings/ForwardRenderer.asset.meta delete mode 100644 sdks/csharp/Assets/Settings/SampleSceneProfile.asset delete mode 100644 sdks/csharp/Assets/Settings/SampleSceneProfile.asset.meta delete mode 100644 sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset delete mode 100644 sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset.meta delete mode 100644 sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset delete mode 100644 sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset.meta delete mode 100644 sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset delete mode 100644 sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/System.Buffers.4.4.0.nupkg delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/System.Buffers.4.4.0.nupkg.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/THIRD-PARTY-NOTICES.TXT delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/THIRD-PARTY-NOTICES.TXT.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs.meta delete mode 100644 sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs.meta delete mode 100644 sdks/csharp/Packages/manifest.json delete mode 100644 sdks/csharp/Packages/packages-lock.json delete mode 100644 sdks/csharp/ProjectSettings/AudioManager.asset delete mode 100644 sdks/csharp/ProjectSettings/ClusterInputManager.asset delete mode 100644 sdks/csharp/ProjectSettings/DynamicsManager.asset delete mode 100644 sdks/csharp/ProjectSettings/EditorBuildSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/EditorSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/GraphicsSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/InputManager.asset delete mode 100644 sdks/csharp/ProjectSettings/NavMeshAreas.asset delete mode 100644 sdks/csharp/ProjectSettings/PackageManagerSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/Physics2DSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/PresetManager.asset delete mode 100644 sdks/csharp/ProjectSettings/ProjectSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/ProjectVersion.txt delete mode 100644 sdks/csharp/ProjectSettings/QualitySettings.asset delete mode 100644 sdks/csharp/ProjectSettings/SceneTemplateSettings.json delete mode 100644 sdks/csharp/ProjectSettings/TagManager.asset delete mode 100644 sdks/csharp/ProjectSettings/TimeManager.asset delete mode 100644 sdks/csharp/ProjectSettings/URPProjectSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/UnityConnectSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/VFXManager.asset delete mode 100644 sdks/csharp/ProjectSettings/VersionControlSettings.asset delete mode 100644 sdks/csharp/ProjectSettings/XRSettings.asset create mode 100644 sdks/csharp/SpacetimeDBCSharpSDK.csproj delete mode 100755 sdks/csharp/export.sh rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/ByteArrayConverter.cs (100%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/ClientApi.cs (100%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/ClientApiExtensions.cs (51%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/ClientCache.cs (87%) create mode 100644 sdks/csharp/src/ConsoleLogger.cs rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/IDatabaseTable.cs (86%) create mode 100644 sdks/csharp/src/ILogger.cs rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/Identity.cs (99%) create mode 100644 sdks/csharp/src/NetworkManager.cs rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/ReducerExtensions.cs (100%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/ReducerMismatchException.cs (88%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/SATS/AlgebraicType.cs (100%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/SATS/AlgebraicValue.cs (100%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/SATS/Typespace.cs (93%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts/NetworkManager.cs => src/SpacetimeDBClient.cs} (87%) create mode 100644 sdks/csharp/src/Stubs.cs create mode 100644 sdks/csharp/src/UnityDebugLogger.cs rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/Utils.cs (100%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/WebSocket.cs (97%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/json/EnumAttribute.cs (92%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/json/EnumWrapper.cs (93%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/json/EnumWrapperConverter.cs (97%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/json/JsonContractResolver.cs (93%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/json/SomeAttribute.cs (92%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/json/SomeWrapper.cs (92%) rename sdks/csharp/{Assets/SpacetimeDB/Scripts => src}/json/SomeWrapperConverter.cs (100%) delete mode 100755 sdks/csharp/upload.sh diff --git a/sdks/csharp/.gitignore b/sdks/csharp/.gitignore index 0da27256829..644de291094 100644 --- a/sdks/csharp/.gitignore +++ b/sdks/csharp/.gitignore @@ -1,78 +1,134 @@ -# This .gitignore file should be placed at the root of your Unity project directory -# -# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore -# -/[Ll]ibrary/ -/[Tt]emp/ -/[Oo]bj/ -/[Bb]uild/ -/[Bb]uilds/ -/[Ll]ogs/ -/[Uu]ser[Ss]ettings/ - -# MemoryCaptures can get excessive in size. -# They also could contain extremely sensitive data -/[Mm]emoryCaptures/ - -# Recordings can get excessive in size -/[Rr]ecordings/ - -# Uncomment this line if you wish to ignore the asset store tools plugin -# /[Aa]ssets/AssetStoreTools* - -# Autogenerated Jetbrains Rider plugin -/[Aa]ssets/Plugins/Editor/JetBrains* - -# Visual Studio Code cache directory -.vscode/ - -# Visual Studio cache directory -.vs/ - -# Gradle cache directory -.gradle/ - -# Autogenerated VS/MD/Consulo solution and project files -ExportedObj/ -.consulo/ -*.csproj -*.unityproj -*.sln +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files *.suo -*.tmp *.user -*.userprefs -*.pidb -*.booproj -*.svd +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch *.pdb -*.mdb -*.opendb -*.VC.db +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.svclog +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml +*.azurePubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +packages/ +## TODO: If the tool you use requires repositories.config, also uncomment the next line +!packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +![Ss]tyle[Cc]op.targets +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +.vs + +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm -# Unity3D generated meta files -*.pidb.meta -*.pdb.meta -*.mdb.meta +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf -# Unity3D generated file on crash reports -sysinfo.txt +# ========================= +# Windows detritus +# ========================= -# Builds -*.apk -*.aab -*.unitypackage -*.app +# Windows image file caches +Thumbs.db +ehthumbs.db -# Crashlytics generated file -crashlytics-build.properties +# Folder config file +Desktop.ini -# Packed Addressables -/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* +# Recycle Bin used on file shares +$RECYCLE.BIN/ -# Temporary auto-generated Android Assets -/[Aa]ssets/[Ss]treamingAssets/aa.meta -/[Aa]ssets/[Ss]treamingAssets/aa/* +# Mac desktop service store files +.DS_Store -.idea -*.unitypackage +_NCrunch* \ No newline at end of file diff --git a/sdks/csharp/Assets/ExportPackage.cs b/sdks/csharp/Assets/ExportPackage.cs deleted file mode 100644 index 70e15566919..00000000000 --- a/sdks/csharp/Assets/ExportPackage.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; - -public class ExportPackage -{ - public static void Export() - { - AssetDatabase.ExportPackage("Assets/SpacetimeDB", "SpacetimeDBUnitySDK.unitypackage", ExportPackageOptions.Recurse); - } -} diff --git a/sdks/csharp/Assets/ExportPackage.cs.meta b/sdks/csharp/Assets/ExportPackage.cs.meta deleted file mode 100644 index d56b6fc11df..00000000000 --- a/sdks/csharp/Assets/ExportPackage.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 54770d36c73a74a6db05cfc84d75f761 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Main.unity b/sdks/csharp/Assets/Main.unity deleted file mode 100644 index 7582fbead7b..00000000000 --- a/sdks/csharp/Assets/Main.unity +++ /dev/null @@ -1,301 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.18028328, g: 0.22571328, b: 0.3069218, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_LightingSettings: {fileID: 0} ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &870692381 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 870692384} - - component: {fileID: 870692383} - - component: {fileID: 870692382} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &870692382 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 870692381} - m_Enabled: 1 ---- !u!20 &870692383 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 870692381} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &870692384 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 870692381} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1777449238 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1777449240} - - component: {fileID: 1777449239} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &1777449239 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1777449238} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.02 - m_NormalBias: 0.1 - m_NearPlane: 0.1 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_UseViewFrustumForShadowCasterCull: 1 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &1777449240 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1777449238} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} diff --git a/sdks/csharp/Assets/Main.unity.meta b/sdks/csharp/Assets/Main.unity.meta deleted file mode 100644 index 56f79e86662..00000000000 --- a/sdks/csharp/Assets/Main.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b7991f809bde6e4419a94e030a8bcb16 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Materials.meta b/sdks/csharp/Assets/Materials.meta deleted file mode 100644 index ee17c23bb89..00000000000 --- a/sdks/csharp/Assets/Materials.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d0234ba368eeec9418390da711bfdad0 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Materials/Skybox_Mat.mat b/sdks/csharp/Assets/Materials/Skybox_Mat.mat deleted file mode 100644 index ba73d5da58f..00000000000 --- a/sdks/csharp/Assets/Materials/Skybox_Mat.mat +++ /dev/null @@ -1,89 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: Skybox_Mat - m_Shader: {fileID: 106, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _METALLIC_SETUP _SUNDISK_HIGH_QUALITY - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _SpecGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _AtmosphereThickness: 0.53 - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _Exposure: 1.25 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 0 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _SunDisk: 2 - - _SunSize: 0.04 - - _SunSizeConvergence: 5 - - _UVSec: 0 - - _WorkflowMode: 1 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 1, g: 1, b: 1, a: 1} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - - _GroundColor: {r: 0.6392157, g: 0.6901961, b: 0.7411765, a: 1} - - _SkyTint: {r: 1, g: 1, b: 1, a: 1} - - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} diff --git a/sdks/csharp/Assets/Materials/Skybox_Mat.mat.meta b/sdks/csharp/Assets/Materials/Skybox_Mat.mat.meta deleted file mode 100644 index facef4afefe..00000000000 --- a/sdks/csharp/Assets/Materials/Skybox_Mat.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0ffaa0b7117ba8c47a9d05ae701d4b4d -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets.meta b/sdks/csharp/Assets/Presets.meta deleted file mode 100644 index c3a6623f4d5..00000000000 --- a/sdks/csharp/Assets/Presets.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 558255460b74ec04fa70b5570e9327bd -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset b/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset deleted file mode 100644 index 4ca91acf3df..00000000000 --- a/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset +++ /dev/null @@ -1,137 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!181963792 &2655988077585873504 -Preset: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: AudioCompressedInMemory - m_TargetType: - m_NativeTypeID: 1020 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - m_Properties: - - target: {fileID: 0} - propertyPath: m_ExternalObjects.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.loadType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.compressionFormat - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.quality - value: 0.7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.size - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].first - value: 4 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.loadType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.compressionFormat - value: 3 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.quality - value: 0.7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].first - value: 7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.loadType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.compressionFormat - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.quality - value: 0.7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ForceToMono - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Normalize - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PreloadAudioData - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_LoadInBackground - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Ambisonic - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_3D - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_UserData - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleName - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleVariant - value: - objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset.meta b/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset.meta deleted file mode 100644 index cd0d5633dc2..00000000000 --- a/sdks/csharp/Assets/Presets/AudioCompressedInMemory.preset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2dd802e4d37c65149922028d3e973832 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/AudioStreaming.preset b/sdks/csharp/Assets/Presets/AudioStreaming.preset deleted file mode 100644 index 8499ed8c629..00000000000 --- a/sdks/csharp/Assets/Presets/AudioStreaming.preset +++ /dev/null @@ -1,137 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!181963792 &2655988077585873504 -Preset: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: AudioStreaming - m_TargetType: - m_NativeTypeID: 1020 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - m_Properties: - - target: {fileID: 0} - propertyPath: m_ExternalObjects.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.loadType - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.compressionFormat - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.quality - value: 0.7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.size - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].first - value: 4 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.loadType - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.compressionFormat - value: 3 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.quality - value: 0.7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].first - value: 7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.loadType - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.compressionFormat - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.quality - value: 0.7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ForceToMono - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Normalize - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PreloadAudioData - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_LoadInBackground - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Ambisonic - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_3D - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_UserData - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleName - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleVariant - value: - objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/AudioStreaming.preset.meta b/sdks/csharp/Assets/Presets/AudioStreaming.preset.meta deleted file mode 100644 index b7b81180255..00000000000 --- a/sdks/csharp/Assets/Presets/AudioStreaming.preset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 86bcce7f5575b54408aa0f3a7d321039 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2655988077585873504 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/Defaults.meta b/sdks/csharp/Assets/Presets/Defaults.meta deleted file mode 100644 index 959a49bd8da..00000000000 --- a/sdks/csharp/Assets/Presets/Defaults.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 71ea82b02df99c2439e0dc8e4e1ebc24 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset b/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset deleted file mode 100644 index 6137100f126..00000000000 --- a/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset +++ /dev/null @@ -1,497 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!181963792 &2655988077585873504 -Preset: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: AlbedoTexture_Default - m_TargetType: - m_NativeTypeID: 1006 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - m_Properties: - - target: {fileID: 0} - propertyPath: m_FileIDToRecycleName.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ExternalObjects.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_EnableMipMap - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_sRGBTexture - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_LinearTexture - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_FadeOut - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_BorderMipMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapsPreserveCoverage - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaTestReferenceValue - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapFadeDistanceStart - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapFadeDistanceEnd - value: 3 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ConvertToNormalMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ExternalNormalMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_HeightScale - value: 0.25 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_NormalMapFilter - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_IsReadable - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_StreamingMipmaps - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_StreamingMipmapsPriority - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_GrayScaleToAlpha - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_GenerateCubemap - value: 6 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CubemapConvolution - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SeamlessCubemap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureFormat - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MaxTextureSize - value: 2048 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_FilterMode - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_Aniso - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_MipBias - value: -100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapU - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapV - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapW - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_NPOTScale - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Lightmap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteExtrude - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteMeshType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Alignment - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePivot.x - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePivot.y - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePixelsToUnits - value: 100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.w - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteGenerateFallbackPhysicsShape - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaUsage - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaIsTransparency - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteTessellationDetail - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureType - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureShape - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SingleChannelComponent - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MaxTextureSizeSet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CompressionQualitySet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureFormatSet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.size - value: 5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget - value: DefaultTexturePlatform - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget - value: Standalone - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_BuildTarget - value: iPhone - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_BuildTarget - value: Android - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_BuildTarget - value: Windows Store Apps - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Sprites.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Outline.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Bones.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_SpriteID - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Vertices.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Indices.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Edges.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Weights.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePackingTag - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PSDRemoveMatte - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PSDShowRemoveMatteOption - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_UserData - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleName - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleVariant - value: - objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset.meta b/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset.meta deleted file mode 100644 index 2e7fd878e49..00000000000 --- a/sdks/csharp/Assets/Presets/Defaults/AlbedoTexture_Default.preset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e8537455c6c08bd4e8bf0be3707da685 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2655988077585873504 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset b/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset deleted file mode 100644 index dd415f614c9..00000000000 --- a/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset +++ /dev/null @@ -1,137 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!181963792 &2655988077585873504 -Preset: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: AudioDecompressOnLoad - m_TargetType: - m_NativeTypeID: 1020 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - m_Properties: - - target: {fileID: 0} - propertyPath: m_ExternalObjects.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.loadType - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.compressionFormat - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.quality - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DefaultSettings.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.size - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].first - value: 4 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.loadType - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.compressionFormat - value: 3 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.quality - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[0].second.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].first - value: 7 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.loadType - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateSetting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.sampleRateOverride - value: 44100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.compressionFormat - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.quality - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettingOverrides.Array.data[1].second.conversionMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ForceToMono - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Normalize - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PreloadAudioData - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_LoadInBackground - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Ambisonic - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_3D - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_UserData - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleName - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleVariant - value: - objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset.meta b/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset.meta deleted file mode 100644 index 8e3dd0256da..00000000000 --- a/sdks/csharp/Assets/Presets/Defaults/AudioDecompressOnLoad.preset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e7689051185d12f4298e1ebb2693a29f -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset b/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset deleted file mode 100644 index 24034e46df9..00000000000 --- a/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset +++ /dev/null @@ -1,137 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!181963792 &2655988077585873504 -Preset: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: DirectionalLight_Default - m_TargetType: - m_NativeTypeID: 108 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - m_Properties: - - target: {fileID: 0} - propertyPath: m_Enabled - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Type - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Color.r - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Color.g - value: 0.95686275 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Color.b - value: 0.8392157 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Color.a - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Intensity - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Range - value: 10 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpotAngle - value: 30 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CookieSize - value: 10 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Shadows.m_Type - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Shadows.m_Resolution - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Shadows.m_CustomResolution - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Shadows.m_Strength - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Shadows.m_Bias - value: 0.02 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Shadows.m_NormalBias - value: 0.1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Shadows.m_NearPlane - value: 0.1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Cookie - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_DrawHalo - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Flare - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_RenderMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CullingMask.m_Bits - value: 4294967295 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Lightmapping - value: 4 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_LightShadowCasterMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AreaSize.x - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AreaSize.y - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_BounceIntensity - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ColorTemperature - value: 6570 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_UseColorTemperature - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ShadowRadius - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ShadowAngle - value: 0 - objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset.meta b/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset.meta deleted file mode 100644 index ac83bf91c7c..00000000000 --- a/sdks/csharp/Assets/Presets/Defaults/DirectionalLight_Default.preset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 463065d4f17d1d94d848aa127b94dd43 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2655988077585873504 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/NormalTexture.preset b/sdks/csharp/Assets/Presets/NormalTexture.preset deleted file mode 100644 index c6a771f40e8..00000000000 --- a/sdks/csharp/Assets/Presets/NormalTexture.preset +++ /dev/null @@ -1,497 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!181963792 &2655988077585873504 -Preset: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: NormalTexture - m_TargetType: - m_NativeTypeID: 1006 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - m_Properties: - - target: {fileID: 0} - propertyPath: m_FileIDToRecycleName.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ExternalObjects.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_EnableMipMap - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_sRGBTexture - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_LinearTexture - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_FadeOut - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_BorderMipMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapsPreserveCoverage - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaTestReferenceValue - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapFadeDistanceStart - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapFadeDistanceEnd - value: 3 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ConvertToNormalMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ExternalNormalMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_HeightScale - value: 0.25 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_NormalMapFilter - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_IsReadable - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_StreamingMipmaps - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_StreamingMipmapsPriority - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_GrayScaleToAlpha - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_GenerateCubemap - value: 6 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CubemapConvolution - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SeamlessCubemap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureFormat - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MaxTextureSize - value: 2048 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_FilterMode - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_Aniso - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_MipBias - value: -100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapU - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapV - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapW - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_NPOTScale - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Lightmap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteExtrude - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteMeshType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Alignment - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePivot.x - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePivot.y - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePixelsToUnits - value: 100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.w - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteGenerateFallbackPhysicsShape - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaUsage - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaIsTransparency - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteTessellationDetail - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureShape - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SingleChannelComponent - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MaxTextureSizeSet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CompressionQualitySet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureFormatSet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.size - value: 5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget - value: DefaultTexturePlatform - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget - value: Standalone - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_BuildTarget - value: iPhone - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_BuildTarget - value: Android - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_BuildTarget - value: Windows Store Apps - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Sprites.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Outline.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Bones.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_SpriteID - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Vertices.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Indices.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Edges.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Weights.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePackingTag - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PSDRemoveMatte - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PSDShowRemoveMatteOption - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_UserData - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleName - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleVariant - value: - objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/NormalTexture.preset.meta b/sdks/csharp/Assets/Presets/NormalTexture.preset.meta deleted file mode 100644 index 33fcecf55be..00000000000 --- a/sdks/csharp/Assets/Presets/NormalTexture.preset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 14a57cf3b9fa1c74b884aa7e0dcf1faa -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2655988077585873504 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Presets/UtilityTexture.preset b/sdks/csharp/Assets/Presets/UtilityTexture.preset deleted file mode 100644 index 6b879d82c31..00000000000 --- a/sdks/csharp/Assets/Presets/UtilityTexture.preset +++ /dev/null @@ -1,497 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!181963792 &2655988077585873504 -Preset: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: UtilityTexture - m_TargetType: - m_NativeTypeID: 1006 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - m_Properties: - - target: {fileID: 0} - propertyPath: m_FileIDToRecycleName.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ExternalObjects.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_EnableMipMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_sRGBTexture - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_LinearTexture - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_FadeOut - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_BorderMipMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapsPreserveCoverage - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaTestReferenceValue - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapFadeDistanceStart - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MipMapFadeDistanceEnd - value: 3 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ConvertToNormalMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_ExternalNormalMap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_HeightScale - value: 0.25 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_NormalMapFilter - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_IsReadable - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_StreamingMipmaps - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_StreamingMipmapsPriority - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_GrayScaleToAlpha - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_GenerateCubemap - value: 6 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CubemapConvolution - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SeamlessCubemap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureFormat - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MaxTextureSize - value: 2048 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_FilterMode - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_Aniso - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_MipBias - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapU - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapV - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureSettings.m_WrapW - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_NPOTScale - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Lightmap - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteMode - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteExtrude - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteMeshType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_Alignment - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePivot.x - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePivot.y - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePixelsToUnits - value: 100 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteBorder.w - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteGenerateFallbackPhysicsShape - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaUsage - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AlphaIsTransparency - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteTessellationDetail - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureType - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureShape - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SingleChannelComponent - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_MaxTextureSizeSet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_CompressionQualitySet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_TextureFormatSet - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.size - value: 5 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget - value: DefaultTexturePlatform - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget - value: Standalone - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_BuildTarget - value: iPhone - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[2].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_BuildTarget - value: Android - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_TextureCompression - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[3].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_BuildTarget - value: Windows Store Apps - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_MaxTextureSize - value: 8192 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_ResizeAlgorithm - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_TextureFormat - value: -1 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_TextureCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_CompressionQuality - value: 50 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_CrunchedCompression - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_AllowsAlphaSplitting - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_Overridden - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PlatformSettings.Array.data[4].m_AndroidETC2FallbackOverride - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Sprites.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Outline.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Bones.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_SpriteID - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Vertices.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Indices.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Edges.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpriteSheet.m_Weights.Array.size - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_SpritePackingTag - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PSDRemoveMatte - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_PSDShowRemoveMatteOption - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_UserData - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleName - value: - objectReference: {fileID: 0} - - target: {fileID: 0} - propertyPath: m_AssetBundleVariant - value: - objectReference: {fileID: 0} diff --git a/sdks/csharp/Assets/Presets/UtilityTexture.preset.meta b/sdks/csharp/Assets/Presets/UtilityTexture.preset.meta deleted file mode 100644 index a11d2e93d1b..00000000000 --- a/sdks/csharp/Assets/Presets/UtilityTexture.preset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 45f7b2e3c78185248b3adbb14429c2ab -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2655988077585873504 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings.meta b/sdks/csharp/Assets/Settings.meta deleted file mode 100644 index 8e9f13c8f03..00000000000 --- a/sdks/csharp/Assets/Settings.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0735c275001a2c84dafdb30deced5d8d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/ForwardRenderer.asset b/sdks/csharp/Assets/Settings/ForwardRenderer.asset deleted file mode 100644 index 4514a2b8a1a..00000000000 --- a/sdks/csharp/Assets/Settings/ForwardRenderer.asset +++ /dev/null @@ -1,36 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} - m_Name: ForwardRenderer - m_EditorClassIdentifier: - m_RendererFeatures: [] - postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} - shaders: - blitPS: {fileID: 4800000, guid: c17132b1f77d20942aa75f8429c0f8bc, type: 3} - copyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} - screenSpaceShadowPS: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, - type: 3} - samplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} - fallbackErrorPS: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} - m_OpaqueLayerMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_TransparentLayerMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_DefaultStencilState: - overrideStencilState: 0 - stencilReference: 0 - stencilCompareFunction: 8 - passOperation: 0 - failOperation: 0 - zFailOperation: 0 diff --git a/sdks/csharp/Assets/Settings/ForwardRenderer.asset.meta b/sdks/csharp/Assets/Settings/ForwardRenderer.asset.meta deleted file mode 100644 index 06d9cabc24e..00000000000 --- a/sdks/csharp/Assets/Settings/ForwardRenderer.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4a8e21d5c33334b11b34a596161b9360 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/SampleSceneProfile.asset b/sdks/csharp/Assets/Settings/SampleSceneProfile.asset deleted file mode 100644 index cbc629b5cd2..00000000000 --- a/sdks/csharp/Assets/Settings/SampleSceneProfile.asset +++ /dev/null @@ -1,118 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &-7893295128165547882 -MonoBehaviour: - m_ObjectHideFlags: 3 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0b2db86121404754db890f4c8dfe81b2, type: 3} - m_Name: Bloom - m_EditorClassIdentifier: - active: 1 - m_AdvancedMode: 0 - threshold: - m_OverrideState: 1 - m_Value: 1 - min: 0 - intensity: - m_OverrideState: 1 - m_Value: 1 - min: 0 - scatter: - m_OverrideState: 0 - m_Value: 0.7 - min: 0 - max: 1 - clamp: - m_OverrideState: 0 - m_Value: 65472 - min: 0 - tint: - m_OverrideState: 0 - m_Value: {r: 1, g: 1, b: 1, a: 1} - hdr: 0 - showAlpha: 0 - showEyeDropper: 1 - highQualityFiltering: - m_OverrideState: 0 - m_Value: 0 - dirtTexture: - m_OverrideState: 0 - m_Value: {fileID: 0} - dirtIntensity: - m_OverrideState: 0 - m_Value: 0 - min: 0 ---- !u!114 &-7011558710299706105 -MonoBehaviour: - m_ObjectHideFlags: 3 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 899c54efeace73346a0a16faa3afe726, type: 3} - m_Name: Vignette - m_EditorClassIdentifier: - active: 1 - m_AdvancedMode: 0 - color: - m_OverrideState: 0 - m_Value: {r: 0, g: 0, b: 0, a: 1} - hdr: 0 - showAlpha: 0 - showEyeDropper: 1 - center: - m_OverrideState: 0 - m_Value: {x: 0.5, y: 0.5} - intensity: - m_OverrideState: 1 - m_Value: 0.25 - min: 0 - max: 1 - smoothness: - m_OverrideState: 1 - m_Value: 0.4 - min: 0.01 - max: 1 - rounded: - m_OverrideState: 0 - m_Value: 0 ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3} - m_Name: SampleSceneProfile - m_EditorClassIdentifier: - components: - - {fileID: 849379129802519247} - - {fileID: -7893295128165547882} - - {fileID: -7011558710299706105} ---- !u!114 &849379129802519247 -MonoBehaviour: - m_ObjectHideFlags: 3 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 97c23e3b12dc18c42a140437e53d3951, type: 3} - m_Name: Tonemapping - m_EditorClassIdentifier: - active: 1 - m_AdvancedMode: 0 - mode: - m_OverrideState: 1 - m_Value: 2 diff --git a/sdks/csharp/Assets/Settings/SampleSceneProfile.asset.meta b/sdks/csharp/Assets/Settings/SampleSceneProfile.asset.meta deleted file mode 100644 index b82270c5b28..00000000000 --- a/sdks/csharp/Assets/Settings/SampleSceneProfile.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 10fc4df2da32a41aaa32d77bc913491c -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset b/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset deleted file mode 100644 index 2ac23c8bcd5..00000000000 --- a/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset +++ /dev/null @@ -1,53 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} - m_Name: UniversalRP-HighQuality - m_EditorClassIdentifier: - k_AssetVersion: 5 - k_AssetPreviousVersion: 5 - m_RendererType: 1 - m_RendererData: {fileID: 0} - m_RendererDataList: - - {fileID: 11400000, guid: 4a8e21d5c33334b11b34a596161b9360, type: 2} - m_DefaultRendererIndex: 0 - m_RequireDepthTexture: 0 - m_RequireOpaqueTexture: 0 - m_OpaqueDownsampling: 1 - m_SupportsHDR: 1 - m_MSAA: 2 - m_RenderScale: 1 - m_MainLightRenderingMode: 1 - m_MainLightShadowsSupported: 1 - m_MainLightShadowmapResolution: 2048 - m_AdditionalLightsRenderingMode: 1 - m_AdditionalLightsPerObjectLimit: 4 - m_AdditionalLightShadowsSupported: 1 - m_AdditionalLightsShadowmapResolution: 512 - m_ShadowDistance: 50 - m_ShadowCascades: 1 - m_Cascade2Split: 0.25 - m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} - m_ShadowDepthBias: 1 - m_ShadowNormalBias: 1 - m_SoftShadowsSupported: 1 - m_UseSRPBatcher: 1 - m_SupportsDynamicBatching: 0 - m_MixedLightingSupported: 1 - m_DebugLevel: 0 - m_ColorGradingMode: 0 - m_ColorGradingLutSize: 32 - m_ShadowType: 1 - m_LocalShadowsSupported: 0 - m_LocalShadowsAtlasResolution: 256 - m_MaxPixelLights: 0 - m_ShadowAtlasResolution: 256 - m_ShaderVariantLogLevel: 0 diff --git a/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset.meta b/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset.meta deleted file mode 100644 index c8fa31758a9..00000000000 --- a/sdks/csharp/Assets/Settings/UniversalRP-HighQuality.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 19ba41d7c0026c3459d37c2fe90c55a0 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset b/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset deleted file mode 100644 index ab81d03f0fb..00000000000 --- a/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset +++ /dev/null @@ -1,53 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} - m_Name: UniversalRP-LowQuality - m_EditorClassIdentifier: - k_AssetVersion: 5 - k_AssetPreviousVersion: 5 - m_RendererType: 1 - m_RendererData: {fileID: 0} - m_RendererDataList: - - {fileID: 11400000, guid: 4a8e21d5c33334b11b34a596161b9360, type: 2} - m_DefaultRendererIndex: 0 - m_RequireDepthTexture: 0 - m_RequireOpaqueTexture: 0 - m_OpaqueDownsampling: 1 - m_SupportsHDR: 0 - m_MSAA: 1 - m_RenderScale: 1 - m_MainLightRenderingMode: 1 - m_MainLightShadowsSupported: 0 - m_MainLightShadowmapResolution: 2048 - m_AdditionalLightsRenderingMode: 0 - m_AdditionalLightsPerObjectLimit: 4 - m_AdditionalLightShadowsSupported: 0 - m_AdditionalLightsShadowmapResolution: 512 - m_ShadowDistance: 50 - m_ShadowCascades: 0 - m_Cascade2Split: 0.25 - m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} - m_ShadowDepthBias: 1 - m_ShadowNormalBias: 1 - m_SoftShadowsSupported: 0 - m_UseSRPBatcher: 1 - m_SupportsDynamicBatching: 0 - m_MixedLightingSupported: 1 - m_DebugLevel: 0 - m_ColorGradingMode: 0 - m_ColorGradingLutSize: 16 - m_ShadowType: 1 - m_LocalShadowsSupported: 0 - m_LocalShadowsAtlasResolution: 256 - m_MaxPixelLights: 0 - m_ShadowAtlasResolution: 256 - m_ShaderVariantLogLevel: 0 diff --git a/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset.meta b/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset.meta deleted file mode 100644 index 040da39e5b0..00000000000 --- a/sdks/csharp/Assets/Settings/UniversalRP-LowQuality.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a31e9f9f9c9d4b9429ed0d1234e22103 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset b/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset deleted file mode 100644 index 23de11bf084..00000000000 --- a/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset +++ /dev/null @@ -1,53 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} - m_Name: UniversalRP-MediumQuality - m_EditorClassIdentifier: - k_AssetVersion: 5 - k_AssetPreviousVersion: 5 - m_RendererType: 1 - m_RendererData: {fileID: 0} - m_RendererDataList: - - {fileID: 11400000, guid: 4a8e21d5c33334b11b34a596161b9360, type: 2} - m_DefaultRendererIndex: 0 - m_RequireDepthTexture: 0 - m_RequireOpaqueTexture: 0 - m_OpaqueDownsampling: 1 - m_SupportsHDR: 0 - m_MSAA: 1 - m_RenderScale: 1 - m_MainLightRenderingMode: 1 - m_MainLightShadowsSupported: 1 - m_MainLightShadowmapResolution: 2048 - m_AdditionalLightsRenderingMode: 1 - m_AdditionalLightsPerObjectLimit: 4 - m_AdditionalLightShadowsSupported: 0 - m_AdditionalLightsShadowmapResolution: 512 - m_ShadowDistance: 50 - m_ShadowCascades: 0 - m_Cascade2Split: 0.25 - m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} - m_ShadowDepthBias: 1 - m_ShadowNormalBias: 1 - m_SoftShadowsSupported: 0 - m_UseSRPBatcher: 1 - m_SupportsDynamicBatching: 0 - m_MixedLightingSupported: 1 - m_DebugLevel: 0 - m_ColorGradingMode: 0 - m_ColorGradingLutSize: 32 - m_ShadowType: 1 - m_LocalShadowsSupported: 0 - m_LocalShadowsAtlasResolution: 256 - m_MaxPixelLights: 0 - m_ShadowAtlasResolution: 256 - m_ShaderVariantLogLevel: 0 diff --git a/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset.meta b/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset.meta deleted file mode 100644 index d8477b75449..00000000000 --- a/sdks/csharp/Assets/Settings/UniversalRP-MediumQuality.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d847b876476d3d6468f5dfcd34266f96 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB.meta b/sdks/csharp/Assets/SpacetimeDB.meta deleted file mode 100644 index 5dc6b0124a4..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8c3f00f56e2ad68e986763d9f99b3e1d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages.meta b/sdks/csharp/Assets/SpacetimeDB/Packages.meta deleted file mode 100644 index 223280800ba..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 086bf95e1033970ad9bf698d2215ebac -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9.meta deleted file mode 100644 index 72c8721ddb7..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 345dd82d825150bb68d5624d1e1392ce -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg deleted file mode 100644 index 1758cdd1b7e962d7c75317d3a9038328d8a3efca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1208111 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
    fX`3 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 PkBqR-?P+CubS8py(RN01~ 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�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�qMI{h55)M^ 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
    R(Ow2H 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

    HPG(j2*)3}gs2{Q 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 z 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 z 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 *%Iw18 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 z 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

  • +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

    }j5`_hbk`J=^`}wRw#$CT-n-mV8%*{+m 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 z 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

    n{aZIJX6A0JZJ#pIW;+Iuve?Eo7#`rW?B6A3R zk*axae%Q!Im+(4TtNSr>` zz19Ur(my{Ew&bR5^ccHoilAwgxk>4!1KN7iDBQG+plMC?{wOyp-LwsG6M@@CaD(mA zduV;P;lNU}d)v@>)O;&WPCfsC=2B?1=ul9J9(pPnztc zqGV*5>6HZEu+jFXthqnpSQ<@V1pUcrY8lzf&7V3jHcu{D%~c39+IAoo3F`N-0;!s0 zby8%is4iL8cTd_ZsVd1;5b{kz7T(8pep72DosW5sz|wVbg4PhUKi!K%<7&fs9MS`i zmd!UT?}YW0zoIN`)aGibplL&{W=sabpew13Sc~3e^cd=0imhxjSo0rJ>*}RF#e=oR zUAytH4M`;%S9|9RWB1#fgjw@p@fs->g zQ3WaO$l7p(?-rz#J-$tJZ>Om>$QYB1Et=>4qC6i{p07C11j*CWM68)dJ|38q4boOi zkDA`Fyt$q<-N!MuS7gnpqGO?=gT^XL1#({<%B}l<6Dj-}cgSS+?4icZ8N-s4Q*J;~ z5go5gCU>lxx@VCX_X^LM#Pb{CDf64d)0NBzq~$@ImeWmr{Rn97pBwJ-lto@&hs*Wis*^8 zmYZKjMPN^Nh&5A5p{;`km*DqDqW-PaIc@HzqX4n*-@!&Y$yz)-md|2RZM2IY2bFBf_GRJUfRj732|2Vr2@G6QeJbPPu z4{3xH2q7d8NC*fCBoK1b=mbLO0RjjCg7lUUKp@hUB279X>QhwYS$Kkq3W|Utc0_$5 zh@j{Lq{=)0nVoy@QhbH)Z*|%EvbW`t{JH%pzt#h>S;a{ptzwFC_r&jDNt~^ z?Ef*m-g4C?niKYzdBmuJ&9d!JVRhTs_Pdh$0+g^AsIMgTH7E}wbwN_6KzSOeKnqjf zgYq&`4JCCNl(&)UE~&Gie2mm6N&O7U*GMgs)Gwg?jMPp^{RYb4NbQrQhPm z0V>c){UoXDpn{ClO-bDX6>OyZtV{_nqG}nbx{@-33Ncd6C1nE@YNYZdhwUHAYh3;WYny*K2+1y5cuTvUCY7Snq9SvJZl*I!0Hkq^l56QAX-1Nri)oHd4nV z6$vWFNL`dvG^ki3IkZ-k?Jq0E}&A3R0SyKZZrLL}OX?%Zme=o-?Yrq&@StI|9dD0~wx%Y5$JeP}G@a2P> zp-Gk{A%B`1MN_~TqzkqLD-xSblV$Dr<8b7pgQY@wX1~20ep}z+w;@$*qaHYvMYN#I zj4j-0h_>Xw4Z*-=ItEVm@DjKXbMT*LppWl|RE;Inf}Q(da(Qc~TLNAbM?oag$9-+W zq|GLHO@|F1)mfx40u*Rgr>uMC6P@Q(TO zjfr1-Q89qXkcuCvlf1Vv^R@QdUZWqybsggHSQ;07H;BKSdp{4Wa|Uy{bljK+YKm)ZCVjQ^0vSEX@pqcLFR zH8#Eu<51TxN$2#w;ki;v=_v~kbJ6nvp*DxoLRfX9~2iXt=@}!Dl_ygBsjB%PrV*nX`Ekxl~ybMp#O`pYT#k2`k9HUtTI*sth8A%CEcud zOi9C+Y##ufa9tpi$0Z+D1FUq}^l~$@k*{>X*F?Im2(CEfx;~Ah zmz6e+ibS^Vj9-7WXE1ybd%zLZ!zWsGg7y+5coJCDl{$t; zy}byS61*|be60E!r{T&lKM$wZq@#;F&z#RglG$I_IUhQ9c~6ut8nRUS;lo<#Pain1 zg%+Ps;}d$9N&&J`psW<6cMaN#Vfy1Qo*`5ZD(pk|YBbC7As?ba1#?BPRXsP!&$C_U z>rYL*#{Hx@ZvCX&yU3`-ykta*|G0-KU&ftuKIxedV%2{sFx1LV@i)0`TT6MW zekt&t@6~7~Vv6K(948~hlXJ9Up*sl;vEqcegdHUtO2oC~Va_s^>ftGx?SxPYcUGH97bAbrUzJ?;z!LDl$oLk?@*p9wlqxLspaZ{8c>=#)@@N z5#M9fdHzSiM3Jtsho6ZHjT%FPLS3Z^=ZDEi9ZiUo_^6l-hxmDtdCES})vRI;_?WZw zTo{^-;fZ%gyRoWW6wt0L)P+X2`;l~5SGJ3fikBVjD*HfJvx+^2cI#OUdzUys8~1+< z#c-4J6-qi7xQpHkQz0}tmA0F;V2md#>eENk112~9mTW-2eY!Fpd?=fRN_)k7o9GEI zs;ID=yv6!;&d+$4iJl6m781w3NA#`G!0LK;46S$HV!eClj`c19t_GMB63H+ji3HxV z6PlPX0&8Sl`U*>e!2*MUd`Zu6KBaJrH`5DR3?noTO<=!~t^eJ~G-E!gqlmn>HNPAyeZ3EUQo`lVu&sI~FGc=3ym*fag;ft!i_ zCRS~S>|@f2QoYeiCR3Gp2<<b&__2`$yjkl80@wGN-Su&D{b}Wdi(dG0hD;_cy`!2jq{LSlLngeAg%wI3AURA> zs^c(Ne;y^2zHfi03XKA6@Gt*>wnP35bHWuxTrv{q0Ddl6w&?iP<}Ff-!e9MrGq?Ys z-aozdAaj)Zg?XfF7)V16uVNzpF3X z8?SzE|BBM1Eu~jIhF-QaRq2g=HvSI(Sal3}Z-^EtD0%!6e&a)RMd`S)%h1V|;$(}B zy-a*zGT|Cg&f|+MCuvQFgZsG50mDz~%Q!}=-=gksi%O2NMf)c=!0+idRrM2As;WsD zCftjw$CuPtq02zgcgLj0oo|eE{CxGA#0^y;R$Lof>rL0jlChm@f^Tpv6d~2ySt5aG z?RfT%wIfum9X4;5wc~eFg1a{_7tdi?fS~dVD8C@fyHVaP%YSn$2`FJn@bH#P!gFd# z;JS%byHpl4QK~zxWHME1)sg@tmjrxDXKG2<&CXs@&X{mGV=`6O8lBxDXKDp#h!r3h zab7Xxyq7nQIi$>SKgNCvb7#5B#^2TN=#t+)-kiqpWz6pYMfe#BxWlYQ;V&~;wI%_UoFlDr4JBi)!MDn_2PoIVk!y8jRh4EaCPk>kLUT#p3ZWrK7VV=f3gs+% z0$J1)S(Jh-dY1EN7t5Dq79EyZ)Z2FFH*oYFSrjX?=m@d}g32GE{E;kwg7PP_{GlU@ zP(l{f)wAe`$|A0tSanQId?reD$CXT`O0CKwAelw@l+IKZeZtO;D`!kNoH3cIYmLrs zku#M=jgUo+@6Mt)KCF;3ixL|d!oTdh&EOfshVij>2Ci z586?`F^^Vcf_SO~;kaLD@#-~aiH5W5o@+V8>iF7+zRL6MUt%7pe*($oRU zc1@Z$5}&II=cL(+q)9{4G)K}PL-;+K)jx6KoR^97i%gupcO_0YOsp-Y@!u1y{GF`y z;$N8NMrqa4S;rt0Nmx zLN@l0sm+bx6CRPBS58tB=fi>K`Z>JB^M(nNY&hs>GPR{a6X3KR=pdfS&Nat4ac(%r2U04`6@AnS#KH9DnKD4>IFSA% z4AW&eJUQozTBcBPE>no*X?=}qiJQo2g=+3k-|rb%uUcTe%1NqCr=_@EJTSQ>PEd1` zJaI#LCtGxCaTr$fwFwbv0DD&C|w7inqUThORk=` z5uGMoiR)Io&$+TGSSSNcs*2xOFPHJRP2|;C8%O%nx6>cEiWZ4sCPg(Xs*+-Uz zRjrOFVRalUS4X(R>IN@zb+bWXT;0H7b;GAx-B8A!1yRX8izhTy9#*+$kwmE;btRLj zQmghXKyuHbIh?8U1s`_it(-C8aK>b+t~ENl1!wwt+YIY%waa=t{O=wiE6DxGY;)kwQHJu$GJ$QBBmP% z*(~`%;lEfVImJ6>hBI+o9g`VtwamdNqW<#Vdeg(+^b^US4E=VBB$U2%GF-u$Un zQW?iYwU(-Jk&&o{bE0E`9B)`Srz*V+V7$^-I`q?>dgI_2wruKN1GRn{CxToqC#t29 zLzuuvd#ciL^HW$?sdU`*45X}cGN=_3CADIzF_^CQbz^9qZ0Fr`AUllQNtKP%VZDYWYK`&QquIRUC*17}b`B;=fZ_tq!Y9{%cDkdclj0|B{)7 zTA}o3qBY($AR$)cjmlp97xVR?LXDKWH&Yuyg&C<>No@fYZluyBwH;K1kt&kZQ=n=a zsS3H!Wfv9F)7bK+eQ)|dDJ{8aa^{I||}c|8koev<|~opAQ3iot3fq2t)=)RrWVDEuK=YbHVj zxBdeCZ%YM=QtYHa`p`=z1`y67Jf1$cdr3P@jz8zZ`{Zn#ncs;oc9@*Jh5m1*|DVzS zBvLfxmdpFfUfRUOcJXs1*+wx#AJJ}TPn&o+E3M2X zLfb>0X$N^W8`8$IhBez+9%apzwvZQxlrOf4586Rm+QR3qEcnc6?={dSo>>N&(H62e z8`8HF^7L}ZEcVl^9cumD{44VCQYGXP@9r@+@q)M4Ku;0p3;DY@?0@uutUF+Jh)qPY zJmoDG+C=w3qK8eGxy4#NW~{Y|9X{}o)drfQZ4u9!43r0@qg-n`WQXCb}V_bFNGDPp`! zmfC~|NABLvYv4>h!lA&#xNFZ8Kmudi2E;&^*s09LBx4Me?7z&vSehl&*l+W&m-yEVo^EG+eJKwS%1k7a!Wa6BKK}KTdrh%mte?; zS?*{3whdRhx=eux29tLulGj3UT6D% z@~r!05!(#I7#{D9OxaQe%VZw&oy20LC<}qa>WJG=He|iIptl1}rO^g5F`ApbnK?5r zKz=ow7mOgr%G?K8;DU5i)E1}~z5KJ9(CjC6bstUd4Gk6=p{qTCB1H&uXJUY&L<{C- z^_S=YMjtb(FDk?=T5;bR4AeyIVXkw)uI_2H=Dp4+mr;t?&*;5PuuP?2ww*<&)e4|y z;$!AM^O5KqT&EMO?7O9C%O)DUTu%kc6}cLE+hQ|NzUZo9<^CxRtrv)HjEZzr#Hh?$q8^O8=%^>7 zOx>~{qa2+p)zH7a!*+H5g3usFAL(c?N491L;Gns%flu zu;p;EpSi7c99Gi4@Q{X)n7RmDxj3QWo}VMrB>IVcj-Zivitci`rnwV(oY1Ru^xRAy zgm$k5dPsPgz~y8CO%zEcjEm<2c$p)bG8#M==wZ>B(Wgs+=86&%TK{FSM5Eb@bt-uw zRAEA#r;@?dh#4lt(vXk)V(|#qTfy~~iM5QHESG27} zagbw)=ps&P2=7unLQmkigQ*WSe z#0KU*WA3zgles6?0{tl7X6{|)&WTUWm@n<^-_9RF?`!#-Eu&U|yPzYV&OpD5bBr!_ z0=g;uEEwH|i-0sO)&idk$|Q=jz_MOBkV%VYE|)nUt&;`q%~^-`e6=pHq;GF<0XiDp z1gNey0*H1IK&`aJj7Hdj^0X%zeLfVZtG1V0c!^sm);?k`JO`*mJI-i*E>J)1M@E(H zfl9S&jAk$@)4Z)f4>5XBi)J*I(I_pI(Lio}tY&8v&S-*G!e|b+Fhwh8v~@{%*=R9C ztFj`p4P`(xwMUuDT>(_BEoYQ75@@crozVhDJGBoPb!RUJweyTj%pK8eHjb0gZ(2J> z^B7&#N*I+eayN}*)R<9_X)&WvMs-Zv8BOFCQcQ;#wP!TJ)WVJX$7sH(l+k01wwhKk zdV$eS(=JA{80|5A%qWe~e$z!p@j$e*^>qh&b12YfrlyRBjR5-9)Q3?Lqf4ey?)VO{ zW&&L^RWa9d2+&Q_Tz7%U`T<$YOWmu%^#$@UuVc%HhlQ8DLufrC_v-Mn^O~1=6Qd(D zf&9$Rv6llgP%psz3UjSEvS9NY?pPK7)dncke1N$Ct`}~8-yL%|BqO|Rgorbrb(b?4 z=m8zApNV=IK$sKUqg-=<2UhQotHSA9xSKhOQI{DK#d;u?8bbc2ZsvFo)Emm}bu%Y2 zYRah8Y-jWoM_pzvV)Q+8!_B=tutLAuHoUC27-b&LK8rY(G3HSo)yO{{rH9O8nH#|E zjW<`amv-!Bym=OL6PTN5Ud&wOCe)i^evG`(crGs8JX%aMuVu7$kwoh~uoj$qbl+m2 zja)AyK%&jeU0e!OWj@L+>|$=V`2<_~djriepYy;s>}cAf(8_KO@igOTx(V^Bc!ZFN zQ1USRKF(5en5UJ{S5wK7P`IZ#)?d6B3AD^y#|14n$9m2o%b;06E6s5(+~ej%M(=w8 z?J*ZJ`h?MI<}QrBVf2Q%2cxr$_M3ZgWEqU!GWTIr#OQ!|0Hbn7@0bTMTFdBNa~Y!- z8NFv7L46RS6}@cELpx|5%_v$&54ps7&^(dreP#iA-#mrU->g6%n5XebypjrZ*gS(q ziQaLu0O&(=759DB6rhjI3thP5<|QsId}dz5tzXCxVg#-ETRm~sdty4?AM^tdd3l-9 z8S{2Vmj&wmY~Iaing(>zbN z>tb2Y5~sMkP@JWK3#xBPbV2c!#x7nOSeh#CE|g$t=3?2<(n4`}p+rk77nEda?SdLv zvRqJOOSX&8WQ$#K61i|qEcuF)$c1Za>7Y1?T(}fVXPr|Bxj8ccD?_TKn-?-}j|p6= zrKgK!nx&VQGaJ(_0~kfJWot{Ri)E%|u#2VLGSbV0@6@3{d6qFQmid+mY#C<;Dzr>? zX}yzWhD!^bEi=8g(yDM^iokc9WtP`=`utQ!^Oze|CD8&etS_Sis2-t(jE3mwQARKO z0Clyj@|t5!5=*h=2}UQ}fl4f!7)|sC>SNi;EzFn%)X%cr z#mfN8PUf0d0hL;w<#F+-12o9;5_1v0KxLM{yVM(QIUpnB6}sGVh%I~3FSi7mM_E2# zw3Sc@p(BhM6N(`85u>Suq6mG$UJlfPmr<6_yn^uSuz~pg8*4eq+#KXBkW1?iSxym0 zXNs*cN|P+784b$t+`eVcq6}YFl@B$BJ={_O`Oweh9hgUtIlY z`rcN>)pM#K`!0hlVcCBUWFMB$Yho$ABFsq<#?_&yzkytvEq;V z9$}jJw1G!htmvN%`6_GPiiiA1W5^AxDM|1M>sGzI$xZ(hQE$tBs(Y&D0LgiS&icoS zpC=!t@_@C+T4~~;tP`z@sxPg)>0ea6ljWvvH~qU+&+h`Mb%Ew)SI8sXAS+0=5Nk-f zdV`-Y$>%8Y87r0~fX#~eyN8sTXt($j>7St+-!w74iImip^LT)CRA}%++)hb2IoesHk zu_--PJh;G?-mQAUI8D0L(ql>UWk{@Wp9IVIO1ykrkF1%FR7tv-kGNS}TmsEA-5}epf*i^6 z^SY2LN+4@bEhYOCMYpMZmgUK!vm{?*Z=PhYp>>iglY7wk%;fo29f|ocq+}??ysvUJ z$;bLnBw2gyRFXT^%p&>H8kCQ$d4#0L+Q-uASkGQh<+>B#v$)9)@^)kyj^OUzw@Fhl z{aIpv=)XH1y?BKr<{RBB!ZGh23fX?@{`6)dpvODu0V2NoeHza*(~eTDw`YHmUR>?_ z5Iipp_XsPl-d2I~J7N1@-}Ha z%9kRr%6T+}%<2v4HV5p@*##Lz)y?K$rp1wTdh4irb83nm{@ZfQmC>a%GG9jw&){sO zBl0Rqr+tOPeg#K- zttucl@u+%-K1KG0Vb5^gU5>hu9CMfG*U0nXh_^GGaenxhaz}%XS^+c2#M!Hk^D9=fa`eKO0kXilN=ih6?#+&_|54rdJ+{+&RDf?2v9>P4r z5Q$Igd-eC_3V6tj3T+)L-VBRr{lE1t@g6>nJ-X8yYNg$?mRdbBTg#(XR2@qi*tb{q z4x2ol8=dab_i7D&pS$!0+-})j`Y~+(&|P}j?)1C#w^={;F8x{7FTGQ*kNg^?H>{8= z(!ho-+e#yEUa&*&HSAw-*pC{GNFJ^8I@!D)dVr%n;v79@AIbL!Q)3vz8ar#|v*y$U zXcA*EdxIh|d-t*CT=eJU^S9ck=!k#C8m|~=%#qMo#z6D0I%i1Z6Lyg_wOQjAb)7U3 zVdgf))rUqw)4GmNn^@5$G=wxc4?(j&Duy&KhBs^@kG@97y&08X=2`JucuOjG;1;KJ zM4ZppmZQ|B&Hek8#%=l4foBog@Sbh`!nHo-F+>vd@)ybn;8$-L2=IOD}jE?F< zn!@lQE-{a$ax=E?QD+>n%R;A?plx$XUZ0Dj@Q?0MV zH@AV!GrA4!B;8b|8~b>aYrR(J%$_vl3aYoy5udyOi~LP01Z|HtS8Vc?5I{1xo*(jjQpt8Lyf~eYGoNml2(X4NqV@P z?Fa6CybN`ZaNm#rh2=JmEg|Y8jnzA0Ke~+nMVIlv%;W#(ea7EC^M4;()k@!73NYFi zc^`6(N9i5boYGgD{7mPp>z=7vzsS)BvFE|u`Z11YEo&~Y=Jq&fzUcsOuSURs2X65e z`w!wB(ZOj9qf4yd!EUjYgjXcH6vN` zJ!|%}=1JBZV9jRMJjR+R?!_!_{Svp{f^G8IrY+ly=Q+HE*O0esqxI*w*7rQ~GdZ58 z*yani`GIYgu;vZce8QSlTg5gF+?BH!^h zVDpZM{DInt{3_Qy&Dj)kpZ;FvIDg|>(UH*HtHtpyEmk^O?8CF`$NYJu$q1WAN6MT1 zk0JkR=TOczSMwK=O?KEqvPql>jejTDX8JXJ7;_6g62jiK+s2U)YQ zpn&$GPlRFrT**h@s{m)gJ!m(D9Xsy>3-;rh1MN@fynr?J*z+KLCliq6*qLy&d!lM* z#fo>sm3lDWw^cWxbzvv2?S_h~nnpV)!)JK~{_Nq}6!Wh!5|YO!4k3AY;zW|(^X5~#Cc0ukwbEfZbU5VNk&hC)Cu3C>c2?_1 z*0kPEGPF7@9qiLoK0J6tTCC_f_4zDBvYR4*bkeIN#pG8>V{QBa$qkt&NXA!#{UIZa z#wvq+(zhzhn2c{p4yZg$HebY}tqu*&ku2suj%7JH;aAeMNf?o)&Ov6k_?C{^_~nof z2SavYdC3oQP!QxHUr7IckeS7h)5;+ennQk31G$pzXR>7|*BZ{6SoTKu0c1JPdM;(* ztOxSo@JkfW{KeO@5Sv%qSdp9zO{+%!RPNO%f@Hs>xVE_NkxX(@QZte(Sf_qmrl1%CFlTYRExE$Fio63h9 zb*EZ!^Gm3_dlJSuYBJ+VSam3G&9y3IvDThh;Yh2-;@Z#h~yl37kRuOxp6&B%|bJa<}R zlN9m%v{O{;(#ZVAG`rT?8mEZf4Nnrguin{CEAs@BT|B0f z{M9_0CDUt)lk0cMe zUEs+3`Gtr)_Z}p#28<^8eX#I@em|ABu)akg^rDv3pQdtm(x5!kKSV6>e~8BOxZf3D zn>gtw{OHcYY3&_yU*t`1DPjLWK!}**IhyqU=!&B-aMI7Xe%s(uJ6!X$rPIu5gn2TV zXF_6QlwV20E-rlDZMJDiHYXb2bl5yVEIj*Xt1RBqH=EYgtW3!Iogu^RklG~3?X4g` zSq@pl@{K1T$FMAZ99KR&Ev%JIS1+eW(;eU6ufzJ>t0s;#b$d4?IdD?5Y+P-Q%ci@c zo3|v1Yo2KRHooOox5>up1UaJ~W`8>? zDx)pbZ8Kt5dzz~=W!;yFZAPs)<5`s@ZEW=Id5+3AX}-ztTyMN%B?2(tQOGJCTe$H z*jVEgmCn0Yd-))qN9b=Why0Pb>JHh{|02ndz#HvV9~VAu%PFot zy&Uq3Cu})N|M25+*_4|s7uAF8wFdH`;gEA!_TK{8F%ohJvw69!Ck?XID~I-k<^B$z zFAT?Z#WpP@J48lP04NS@qocI#pPXaqk+yXEek3n!}pf(AarbygCmWw@}x! z^13BEJzQ3 zNZ(S(6Kp@4>;B1pmXJ@`B1YilHW&etGy*U4?mgxIj=xo1oL_&@6*42eZ>H2EPMpoX z+7$Awlz9&Q&%JR57h4S3Z{k9S{vX3}X7R)_$ib_BF$K7|ZtaS+kloPmhP@W(W8TW}ok{CXCO!>$7G) zYu@7P>Ng_fm7Fey*zVQVFg^q7&1d4z^O<-Gw_e59b~c3Hb5zBtKEe<3R5Qq%&79?w zG|0}7F<+598uLdQvb%Q<0UGWM%F)wUj6>fDeF`!ZhnoRwvkjVY^ z{7U-mxycUBU(hrCI+vGLM)w{p(b189K&y20X+M8q78@P)Y6**YS?Au~Sms5$4jna% z1$swE&!q!>sH0cX{e?|@s-w~sWnOOL8y%Ie@E304jE+Ldi@W$$NA>CN^6uiQj(!bJbo6&MHVdLx^Pm!;q(V2^L{KQlpt*Tj`LwCM9(1x4e2R` zK(U3a?H*y>u1jr zmIiXn)()NSo-K+Q&2c|e)Xyhd4AHrDEB%QZtD_@~Ds{`~*(G%Tu|P*HXAiSyi`6=M zd{eo-z1Xg!zik>z=p`NXojlJyN4&11J^d%ybHv*^O3j)<=z|7w1P5l)m3Q&2~`^rj?$MeB6Lbe3Bk(< zozYQo@N{>(_*F;i{rn02p`(}}Sl-rAjc-36yKrkL(b2vo^j?@?9evWX%*!rX>u6M( zHO(#-=_sY#nwBdL=xB1y3VWXTSx001`uXIEf9dFpf&T7!;)ag8`vRF0B{~;4osgG~ z+WLVD)6w-Ha0xnUS^}=Cj{J(&PgfBfN9-kHhK}}hJ7MoFmgy+I%K>{Iv06t{x=oDiD>muq%gz%c`-!bODy2C4izjsy zOmPknFX?D4aRbGE9Tk(8QgKj61=PYIaY;uCGvNbkv?66P_Y=>*yKZIrgdIYaLzf zJIp=}_Y2Al=;=>SDL2y5E0kk1#1tLH(Cn!c2XxenGOkMar%1H0#xr-OXsM&Aesk>A zqEts$23l!e*63&;y`y}#*rlUC01>&#+)yZ8bt~yY?+{GfUnL>%V%S2ZPO3hs%s+-BoN%5a! zUn8E<(VH~ZYsE1gHKhKn6IXTgPa56zA|_4G+nO}{6QZdD#dvHGeF&*lc(a%SgmEbb z+Nh(@l|au*6^C2M-OQQ?=jZ-Sw0l79be85mFN$<@yz?wVm4wv3XP20(bF0$J z?YqQdj2;zQ-kRK9V%Gz5MXA5y>D-sZvX%<%%Y9jNY$cI@_kFp47khQoW5pM_uZouG z5@lBZn!8tY*3s&6bKVDnIl-Cf*^Wdi#;MpmT`qBjMgwB1HDF$k7oZ zJ1!n?D|>6nd&}(;v9Yb31)t}>XZu7vt8+eij}v-XuZO5lh;Iq0I8TV{gjAfL3ZHh) zI6oChgjAfLigH3K&d1az$P2N|chmK7B9?Sb$^w-g8zjb*h#V{T9BJ_=@(9tWt+wx9{ zDLNYMyDslrF-u2t{kG+OCl=^vV({Pcz85QW6hP>oVuOyl2JOlFK|G}+YtY~FPKy_H zloh-u??lV1bs{uQp((Y=a+;2APi{wOwvODo`nxA+ z3v{%qj%|yz09kFmL@sj+3TnL4%#stE$sbken%~)i$oiG z|B>HG8`VX&FlWInLZYj_E9vD`&{g|ZM^l;y7IfE|c4JFI(FHv9oNvsA<6v&G{|Url8D$@Xa+;bN!YXrjXB#s`dpys@~(aVOo3-b)@~paIJ|8dQfZW zK!XEEXxTmFy#8DBf`W3bvySGZ0rk;QOgErmI-0y1Xq=9|?haI?qp}R31v;7()P>OF zI{KX~M`>GioK!GYJ1@P^xkY8cLt4jv z5*?g1zhJx;)?cEn?H?zV?ZZ zayC{LJffX1lc*D+h1#y668WvDELf~<8Ya06SG!T#V4MOu6&7u4= z6+S_`SA{$aH)@B0I5&d}H)~;|^~mC)3b$(8bhMJtlUma;jOg4ls&J?F%^2DG)wra> zXEj@eL_zhF3jd}xt&o=Wb5aYR({jej(H)-Ix^S0P>Ok!aU(gmiP{+a-wcQR>T)6w+ zRNZ%cjn^Ls@MoNJgcxZ>Y+_T?iV+esH^|<(HyaVe9W!;-sjgp->>gI_uljQexEy@=LYpDh~LX$Z)cx;)op|!JPry5%Uo73rQs*l<35+wy6I*v zSJW#Y{#=4apY^$--jZtn?Ny(v>O&BJ^dI1CTCw^P#9v>2g>U-BsxnQ~lo!@VKG)S4 zsWD4l`rMGO$p`4c7_LHDTVqj`8>%)PzwL6B5=s;2Uv8+bLWdl>*Rm=%)jCp?o zV>)p)GQ_{5gBr_P73&0tn`%p`C4ITvrSkex@0)68L-3BCT%xx-ed}mT3@H^l-Eyg~$GnJ?Vep% ze8194ev7*0+gNL4*F)bXT2H&)`Zm=DNY#T|eyz>6*N9&;ZIe`1ztVoqwM#;2u%q&R zEi|{;MlE=1HNRF`52^ht>iD^7FxWtZrFX66j;w z&aTFO?X?ef{oBY>bNvqG=GRfP*yZ8ZNlUh?yI*H*u2em^WfyI$y;fMMt9F%3>?p*q zn^s~D?!oHkrB&q;d)VC2qBY|Z&-%ww-dZOv@mlcCrH3{Egs&kzwJ9Kc4e`-daH$KF z3L$;`e6&Y)4fpfYw7IA>zd)_NUElcyYi@Qe^$XP=gYargg!Tc1^Ae#sWSUo0A~Y8e zUQvnE>TnrXR6s4bRO9N0Rr3-uu5ehjNFi~B1C%Tzu5f@R2^m*7tXig!xWWPYLCUo} zzh%BuMp^y{M}>?l99Hdyka2~>s=W|0u5ehjk3z;34x2{jaT!-QqO?jv#ubhzt+9}C zg(FJqC>2tcD_BTe;Q%E{buPzi6Q$ml=d~=U=2l+I1MwMr(9g4Hl(ti9HGGDS)=n65 z=pE}~iP0{DF!>nmCYO;s)EjVn;pd58wcA1qlr0JO{D0N@|6r)r(tG~fv~yBf37`D8YcZ=0 zIWGO=ze6jM`gzILl9j!0c!QZHby)?|&L(c|0$_Gt-HGsgJ`?APk% z8G5zEKj5I2A+>m1uYkkaE-vxRQUZ=@r?|v3O9}WxyU8V<+0=kz+AA*c%%%n$*BsX3 zGn*T5LaWLpo>^|dN$qPc@mziiIHh&r63-<+phyej63-<+;I!6{OFWnT0cW)FT>Pq6 zbWy-rZMLkftX&jvUR%MXX2a{}p8*%OyLR0Q_*0wole}g+=54@LZHXa=P^&}Wb#0X) zalBvG)`R#X99Z}T)Luwc&aM*pm!|z}Xxzd&fw#2ATq+z@%^C;Z)`CQBiqg8}+kk&G z*L8-*#J&x>zOOvddi=tb z2A^2k2R_l1jfM^f{b+fnt=@$1%-sT?YxOo8kB}Jc7x+T!3F5WEIei0PX>n3nWd{Ym z)<#M-Dc?8njg}!buFlB7x7sqP4g)6yzSFkI`+Qm}J@CDD$f${D{Zac<-m+7(oWPIT zT@ao<|D?HYG0&d=t4##qdG^oRRS@p>vo`iubGM3qTWE@6tGg^v(Y?3Iv+i|Q2derY z5U+KJ-w>$lZMPY*78#Q`3{ ze@xq;YWiIeuf2|F8&pFdUx1$=yn|fzEW2z$b@T$e`UKU}EA2oH4{D$f1>sfMMtT|u zugZRw@ zwe;?(4;4xi-@pR&sfM7_Tywd^r;>r)1N2o~;#0}M?t%I?Lt>VK^xuWDp<}5*LHapE z(6P**P`$}6J|XiI&6*h$p)UjRS}W%jK{h?l5cF?TP>jCW5cIDwC|*Bm2>Q1osJDLB z5cIDosIPv_5cKaxP=EcYA?V-Jpn>|@-Nq}!Z)23;A$r&zfI3f^Fvcl(gnkahYk6ZT z29MG`_KJ1T&HBM(bgLogW>L_1y|*FgW?|4IeUKsOW?@jOKH3m;b5l^7o+{-F&w9E( zSBk=pX6nlgK{pG7X6tLES~wL2&DCQH4ef&@=Ia&r8EOQNzEBSY@yy~Qi-L0WNwRhe zl31!2@ERyTaz)T`z3%VEj{0jUkw2IuLib`1<(uP5vmf>}xp z-lz|=t0?GKeY_!@DtFq`14g>plIR=l{rHS`Q25Z2G_{sxg7@Bu+i7byin#{ALvWRiH(WP<-@#5ac}nOMP}HT zm+F=nk5qiaKQRS+Ui2)`2{08DO}8|Cj{Kx6k6dt#r6T9U=r;c0i&iP-nXOjJo$T__ zaX|@rhC~nMEif*GBhE+IzM$TJE(uAst0#P8H!nFbP9XDdAnwTthT6!=6Wik>$ zhT4DOo7OHE?-+5q8NU{gpcVf_@_;WEX#BLS>tp+Q=2SH=Pie)w*34a!~dxqPOrs_C0-$$_%1Qg!3lB-NBXt+C{? zx0Y-Ps!p8e=H@Bg7`0IIa%G^RL|vgI71|M^Et;w)IPlu#vdEZHXM zD{hhck2fgmBo1(i*r>(7NZ`_G|KLV64tA5(Ys>9seRPRHS`D41 z?TOCp$y1~MI8AF>_>wE%ahS-cdb<0Of0~-Ba8SQ&n)*^a{i|PHuma5;V*z|Cd^Zwl zqC4Lx0LQ_KHI(N-j4^{YxO8^}_k*;YJ|q_e=Z_a8u_LTWqW`EGZ$Su_3T=9q;v>)c<*L!WTnM?>sTjQNCRe+Srnd+E2={UjVt zkJh#?jvzj#gad-_w)c+z*cSYC`5oKD*x(oC3oNv@4Y|%ukU<32vFuDp4Rg*QF|KWtk@kj`l4L9 zL8eH>F&#AxXACkd;73b3qxvSE9!hjxduV~f&KWt9en?KpnGn@QI7&idL%9zg?fbOj z5~1J!-8+dIJX$DtkJhaZ#dDqoP)5XVeQ#Vo+?~m!H#;D?rK5=?7Gz^K5i=e%mvdT= z)?OAryaSn?RW3`$zzW=9&8u*oU+`wl2A7`@hcrt0Dv5reBwRgy*Bv*&BT=+iY~%nA z$oT?y2OfNBR=EF?INm3EIJ-BvSSY*QbxlR^0pNgHL|4Z)z8=X}EK*5RHp{5?aC8!G<)uqK*A=P8cg;H&m?R zACWu4iGbEibdJ1^e?{fwt`wwKKYSs?kuGtN0e4(dw9WvdDk$uVI!^2(-t&+i?szZU z;vsUjhQoMC?jo>7Fdxn!xsr46)d?VV^+BAf*3V$NM)h# zcu<=e-Nb~&(?`TWL$uD;guLOSD8_6da+GK;#EP+jAJTqraRcb5mEaF)zY6*=6}xHe z7$Q)O*?MFHaCbPfD-hRLWa3fvO-{dcOULhmmmbkR8D{!Wh`$$axqaI^U&U5q&zCmm z6IYY4^;5;g$`~EaAnCvi9Z{H%rYbg$%BYi5-O3Bg=Buo}j56hN0hoMmv)6Kquwx%4Ri-TDNM%%kM9;!@V_(TbPWjbgXtvrHnkH-kRDZ)=V1ya&!!; zWi~U3HLjfRL)AXS_zut(t^KI6rosI8Q~|$^uSne$=!j92@TtxFH}p~81Ow7jl(Z{7 zW_&n`_45`y>LTED7w&a}mL)DEmTrkcjM6Q{HK>idlObLd_yLw-#)@{CE%mYiLchVt zk{b5oynISkM=;K@k3H?;D_Ielc=HS7KuUb1|e>(`c%IcjW2;-$v-w*W+vp!WlN|I zD>RRKH)$FC^qxQOJ%aHJ<{&>?!u4|v%f{3Es5d1sQg;PWq6!#5<&ceM=C?p-^@fs} z%w>wVx^q;VWT85{@rt+>9qCKBne-wuY?QG~M6W`3EG%iBP7$!kyzbN_xtoRJ8iE2b zE9m6U=O&VJS-G)46gsp$S_w9v=H*j>bHe3=>ZQjzGCls_4E+r*i`KKhTTE!8rd5<7 zuA5#jf2&RIl(&A`3mK+`lB|m+O{ubq9}e-9a;Wfh^Tq#A?GVcvL@l*pwheWl9Pj-i z@ket5qg$E$z85PLFH!j+*wOo9=;!NnYVz8~)YJ!|yb7fCtF0s>@sGmyX7p&q^m#&! zHBdHji{acu3_HA*M#vS?H?D!b*l7flY$B?iBV`8pDKQmC;pa6|8g&eB!%%dzX zTK$SlYS4#6zpXNZ+8TRRolyafCl5}n-dq2C9nL+$QlGK!L3M>9RqyaR^H|cDI-Efa z%1k&fntO2b42|Ys4eWRX+?!J{Ba-nec49p+r}GTghhOI(kl3o7E-UQ8ULqjvANs)g2d@g_lQ`Ti1O(n_s_#Blk#Osw~_;*vZ$pe z%Q?xSvT$gR{?WaT5uL?9DCl!?MmzJsLq_R-qTlJ^M~{rojY94M zyifS8J9al6;Y-NItIBw&MD?eZvbJm!w+=lpTpWP;4LY3hDlFddA1c?#OghuC3-U7} z^iQ=S7$eW2Ed-pl`U0r>eIP|QEWsPBc>CUZ*!;c5&l&xG732f7?)(Fx^BvAurY~T$ zsSYtvizJk^n?11@U<7684*i43-LC8jEVxCF^wx&+inpBnH94j_KJ^EG z06xGar@^&sOOv5c(8l^iLX6$*TAjd+TjUcnieL<#9n@{ZFkWV6OE_6SGr2$y-6zD; z9aC&hS4UV+aLH*2J{xTPOahb{X#p}CSDUzi3vmEE{tJ-~R`;lV;^g14QG1Xju7!J2 zOYnz!JsP~wjAc4`EXC3fPrPyn#ufod#^BK-iVJ!o!zpkDodxhA7HnWJ96gE81j4aP zaR3w-r>&|7`i3oGUUc09a22`Q6r9D<=MCyU+t~9J$NOw)mG&*m2fGJ-D16-dm?pb# ze22JkU{iDz9}Nr^I7573#eK>lIAi&^K?B^Pt8~x5-TGBOMCr1`(hI>QA(U$OK_W)KEIO;Q9B|Ned#)cQpF z^1bH4Lf#<)4`7r*5KHg%NgSn3yyM&u2Fy>hlEjTmcb*HFA9On8+g8>CJ=Uj+fWD;| zG-ONYwHrZoPFJ8ghgV1HrV&Xr0fMyN=E)YKSb$y=KLUd6fMEgj7g%wFO9!)?2H!hJ z;i$tq^b<2TchZ+qX0)U~R__6@@5z=R8HJYf8QvHqU;x)m;|fIzmD_VoF(9uw`H&_H z(L?%G+#(6Wdym#JNSpX`C3FRFb&^E@2jwdIYlAK|R|JTgBvdZ>r=M85B)R}vsNBat z1Yku74eJib=Qf-{Zp6==P9;(kP$!oAJ-}Gh(<%uPe_Ob(jZ3GJISzyu?hE}x*_xP1 zW{%f^h+`QfaGWA&I9bj2>0QaE?ku3qOqWY8{tUQj84n>JA~0Ox(qv7nB#{N)gvzP^R1;4J zP`rQWEB`G8=MxOoPHGpIg;{@QJ~?VhJaX?rxhWb*T}}8 z6l(^wq!L9_fJ%^w-c3_BnFKfno782KFd*L~Zg&fc5P`prXJPu`}IGoA{A@ zBKrYIYKI#;RF1pY56G~Kz)V$CjXg0?lRiR_pA!^l687eTUjSxDRoy?IfOr#gw*Y51 z)=El_nG2oI2B?Sj(}2BNCeQ$4rUj4!?^Ol0?GI3R!GT4+#hyi5t0usHnYiUutJaWdBsZrwp_Vaf-{8lqnhZQ>tl zVXLGW3sA1>2f%ADU<8DdKBE|e$gJVflJ+D;9V0rrV)rEV8aR^n6orAZCK4bIm2)ke z*Wb`eEu?Cjq-eccZSQZ9bk8R(Bu^_RxBewqKqojGbM*OE;h25#V;#LPC4oVwc>#L| z15cIRwQRsc+BDJjp)|@Qs%poYNXR~OX_;f*udDj$CFdCG9_yi|@7@B<(a{Clg(&Qf zaSam(s(6d8vC&0X1)Y(5n&eyw%}@BCauQ8Ind1 z%xIzkH-&94YHdd`mmrGyv=`)VuYCohKu5!e$y;!CT4#fzhdO74?Fj9Txu+TE*lhZJ zSpym30d_aK9AsVJ z8H2JO`lcWP2omSU3H6~+ggHfYz@pzPRtGwshU`=0p7?$6L+|duDKZvT(Wx1qMZN9h zc1FWOUT;pL zAE0Vgf>ZLy$7zjSX;@ff(s6Pf`c0h9?}V8(ocU)7O3BImQI->-bH=25LDQ{-VLypf zV|*wO{o+-3_2KqAzYmYLVlc51d|cDqay(%9>+_%R7dJL1LhytW(sQOlHnO9t^dB}= zyfodEglSkjr(G!q2I_iybU}o^iD9mEETsN<)JyJ{+VdCy>%~5@Gjd~wUUFs)6C7;pj2%5N zuqa#p)Xxv4os}ax^po#ObyPIOBJ?3s*J2?plEtJUss+#nd+QuYdb#Z;G7^D^&xpnY zbQ3Iqyz-%0Cb6;m5h)4C`X5B@j`fqk111RS3q3aOb{O9*d&sS47#oa}=W9!+u|mld z@^vOG1}3fJ-c>PTZ(I22Oj+Zm?HR!_fI^=YiV?-;x?F)?6hN)r=f5tKvrTj%9ddgQ zmhc~)WFZLv9b(Z$InXZGXZ9PsDl&TC{A)L(|GM1XHxI06NrOLSfU!47e&*C#V=b{=C;^L4NfPc4PCSxi&p@oAJ5|QI|a> zo4Ic=6FR7IgReyEuBf;202~u9TS6>2W2g={eCWQ#gg;o3FABT<5T(LJ;Xl_?Z6Z}1 zTyiqZQc<+H*f4-aMuwMc(EL5wPZh9GbE=Z13-RvE&zlhSRs8b0aQno=b~W`sB03`x z-ev}pugSUu*9ceYHa^K3L%;I2pw}u)C3fuj?q$zDw%C>IZlxV2BfoN0Gsrc~Ij%Vh zTD(erTImSBdDK%xmCLa`L~3*>$Zcq3QrKf@J*jSDvI?qrUg4Z@LN|zsTbV?+Su8wh zZeUW_KXqRIo65BJ4h`nRUZ~X?eYx_*he~64wrp$i)_GZ%f}r4*7dE&%S*G7l>{Zg3 z%oIF(Vcw8LS?CBB8o51jvTd_=GAaKPA9oWHmNL6^BHQtnRWleE8r!RGQ z!xJ~A(SVNj50U|p!b&sI%dV;j`T5MM-Pk}0cFhL_?qlJSXW5qM)p>1gO}OcA43^rA zYvY_lF(K#7g_+6k0AWVe10dLzQlQ0U=ULIDIc)_3 zF6>36o#@1iK9!fpA4kCH;!@fMp}RL#=I@H7uX*bR#AmE|Kk%U8=_@Y=efVu;MTmyC zBu3#JF?z7b`={o&MKGx~0uUsL1563Wu0+ygYudhX`Jr?p@u~TRXRKN1VuYgG7umaq z{RcH_l?>)xBzzzR_&>#keE7|JC4h$al(MqR2}0^v1FfcReCwLT(Wio$#f#uyzDHpi zqg_!Om}^qC#O*A$FZ?T(eyzC>I&wE{w1+N!@2BZvBjc811(zpON=+*M6Z^x|3kmeryw6< zv_vb9H5oME0{oC-fS=8q6hMoVTcRt(9mMYhy0Qdf>bk}yD&f(Lc5lD%v2D7Mo2`Qk zbgUO8o?9igF2sNa=FhIQ#aZ=b9%KJ4E?rk#lRQV#s*E78JL@-%89Ma(*(2z~{d2>R z)#I-6qCb={bco`oo_P9`_=0D2#uFvUkh%V^Ix>h8Sn&my45fQ(-AEU~_~OT&-M>kJ zFxw_Z%JB!lxLY`C-zqYmjCJ9G2!2)ROJDqyuG6f(M_+uq5UjA}g}wz$J6KTMwz~tE z<58RH{*U&;*NPcpAf9gd77NulSBe`Y)QfOJvTfx*;0-$}Sira9eFfYdugu8^ zi`-&sS^)h%v(9;e#FNlyBn%>heNis;BmevbGm+`LGOnd{gTBYG1TyXLf}plXYLP6z zr+_%CL|IU=2EPo^pc{d(#uv7}4;GFmPXu_*}8RBj|MJ8MG14A*>5W52z;HOknY z$a;{yl~;D#J`h|P&OC&jFQg^CQ3`Y;vZ5}{`O+r4_)c}_d+E;;V8D!;9;T(+iYigK zVnw6hQii(M@lys&DghMHeKy?BgXWp%G5nNTRz2$35qwR|S114%lOI|)daLxTG6#J@ zy8i}fm4Zo%Kuv&Pw~)7l8*R5ReFka09e?Tp7-viljA#E2nh5Y??QVbCaudjj3P1@t zeV*N?DwVxk3CMY2;UVn2UH!TEhVfaq^rvv$O}!6f6U$rPCa(=|+Fo8bjQ=r8B=L}~ zwfyI7-He++b&3+7Sx&Cmebh`+CQ4&gLm{R4pew<&(u^vVC#$rLxMbos9T}|#Qlp-0 znSL|>CuG+6MtTCzZ~5xzX*46O4?oleiOQX`3=u%gXO_eM*^m0pJ(B~f^UWvnyuS!il=d`RKe)Uz=PTH=D{#|GaF z1(~nKPBJ5OpbQ--ga4FC+m2N~&r= z&!w-t@HTX+m1$6K=HTBGb>TvjW3X{j(9!9j>9PIwPt^Ej zm!q#`ortl}M;mKxD2Uo^npuYm7Ahk488Lr9^)oRlMmK|?T~ncKIFbg_^tb@}sS>IF zo$8Wi$xk%gaaD9e)NUQ7-#{;>^T0D4#HcW;!!*Pj=$I;B=L?YKG|>QZUq2g<r30J6R0V0H|lD@}SS@3Wbw`C`a3;g=% z>{qwe-ccW!Su+pd!xL3U6HG2U2J_6gx($epz_p0Yi**LacAf)wi z?%UFQ#)X%o84knWT_Q4G`Js%Y1GE2! z4gs_2LrptiwbR{{4_LDM0nw`;aLr)+iOdRVVvL)C@ zq+?e!8W5NWY4hP)91lr5M^qg4de)%>EJZ&{!J`XFtVqT)xhzDXIzDwu?pXC+bxemJ z4$bsrG_#@tnge0>WI8^j#K6KXHD;QS6K2CT37R3QQ+IicS_Rp>O+5>%A!0|3i2k)Is)k zb3nu?!oH~gj%y(1CZCBePy@x-0a52;+TJ&NMR3$MsKWqJ9tjAVe}{X+8?W>~YN~-( zlh{qR!j*d=Yj_8$aa{0RTGl8za;-G5(fYx*$NUOynk-Zp!y@S4v%(rkc;P)>H+Eo+ z%&&^y7WDumM)ScRUI?m@F$Sz9jA7~U&sDNpXEBMI&qqsz>n4|~lhB7SBXej1#{qjd zc-_^8$?*Gfog>H%A|fpES|#Jidwc6RyG*oJ`g&{2+*871EMtI$S|makt+zTQZ_xE7 zNVp801fiRpwuTYV0$~K$90qAu8T2(F-Q04(2@DK zTP%iqQ^FU8WE|&R4;)c+&^CRn*#u&svTYjs2Qh&t>&AfqqbALn-Y%bUSrPZbxzt|o zkQ$liIWQnB+V&qUbdt&)uI-!F?wr|;{xBJLJmX@mjB#y ziduux+MaYlG#~D4tZk5RCZ1q+%sNPT7#=Wn-1mAf@X>^0Dq=S|mgV6w69G?lEB@Cw z*=aOQ#86?9-wS}&)ajytaH5nGu`mKwa-*J#Xm6~UwW>qDKLTq)8QwPy=~|)ID#Zp2 zCZHzC)PBOfamQ!g0Cg3k+vAGyA$`)#}NwTJp~!}E7H_m9LhOkus93UuQkOP>v)$%r#NH$=o_bv&U5=U z7051{nWp9~TJ4j%FdhtMI&bpUKI9mr9_%Q06xUm-N_<^@b5pHvd95YBeeH$*W95Qd8`{?sCH1*IrFTaqikjStALz?u--6k!q?K<&=m8Sx_!h`?8Y0##tpzj z#BS@HF_a)j-7Zt%n~W)eAN)_TmpWYb*o*K0Wdu9WQI|_+$KNG&hvOJ-Ty>zutAYm2 z(we*+rCTR+-~brTc4~Rum!q-=KrOv2%aPfz2bXiC$E)Zp*!LjE)601?UnvX6>(35f8-zoDAzWC3fOZn z!*_SETWE;2-1b!vqTP0;x6Y>^9c}>2xTpiH#&W=JqIq7zPfB3R6~vpMaOCH_q}qfY z>H{-x2DV=HZ*c#i)qu2l#e%WR=?Kts%zaZ`a!y6*?g)TcggBlu&oQz+y^hbxu$@1` zteu#3wyFE;a}m3~YLA@-T&`(ZYu4*RZj^`K9=DLlX;=%=+w<5`&gwjv1qq-Z&)V|p zAspCDgJC>QqMQ_^e{McwivnXCMn@~802-z1Pzr*iMmJ}t?cGt6Qu2sdwNJN=UZ0`u z>u(rstfE|e9Bvfz68P$%Pk#6tumj5pz2*aslfw2zLzI&!(7c~s{i1KqbOy3xi65FY zoR++s!rP zX7lcDQLBB}a|F0uY1eEZ=N8WYECl~cY`uFOW8{|Ji*F(K2rR@rp7ngiu94DzB7=Wf zZ4Ei{DWwo_J@ks-c8chFj*Al=1GMBF;2oqa^V#+EBs+pMPd4oH;yF27Q3MgiTneLJ zHpht9w{cK{+C|mPj!OIDc^AgX<-X%LYU3nKQ_DTaEG`?M+YG#bT-v!trWdNk|N7#7 z%pY#P0x!oWzISF_7H; zXgeMp4&ld_lEOkG!6a#a91E~?H;DYtYc~b<+w$e~^%)kh5U?}W>DM-ISxu`uM$(&y zQ0cXpMW2^=m*Lk2fn~`r6j~=1m`2j6u3(*dG73v1DyVqIQS=8`C?oFgiuhaPUBtdr z!l&M3_~i`yw8{LwgB`cwV@ZyRG*hTfNA7XUR{w?_Yf((v#uxkB$Dw*@Eyv`GHp8wb z(kG1OFvY!#%8zqz+Xc1X_8We4P~BdYC_6sa@TS|p7= zSHB@9WS)joi8$mRZ_uBWNw=&wvZs>LV%1&$qxv!f@aVI zBed-2JJ%4%b+ZF9Ei*LFssX~N67~$6qsJxVu-{`^%&OQsWMdx4sZ~ZE;*gB>LIc)A zM`|aQH&F9xwL-S6P~!q3ShNtPqnaXyK(qq_)-_Vt9Hl=^Gm36HPb@f+knD89PbFX(;KFX z&&Lk41RONLRP>)1=*YQ@|a} zH)~;kUkD~cjQsRp|4M6kgFNdb4taADRH8l zN3y%YbS>WOASyrTQ4Bi>ls?YWxiL^+Li|BW2>aKZ$*az))oFF-68HL2E?F&eUploX z+%DTJ-fT0AF$JHoh?Y{%p}T1YtB*?KY{#l)u8;^v4+Of>e7}q-zG614j$ZfO(0Vyd zpgp$+KMU855v2hQV9HmoD%XRwDH&-o)yFv+qKhG!WTI(XSl@mC8=OqbfD zC!TnuPNNNTIlfb9s^Am{T(}ib;!!?E%Jx^Tot7dfsw&~@a zI>j}yU>G~%J^^P61zaf?n<-PkosR>JG>v}-M~t$_F~u>fFScx)yFeFWfs9~CHN7so z$jZ&PewNPr29Z}AadSz9d7tBG^yZ5+F;1vnssR1y4yy0;*Y5Y^w;^fv(2l;)R-qLc zGWyX?E-~-x(cKX-XM3WCQ!ZnX0Bx1Gd%Q2PknPQ+5W+JXsi`JCQ(>WP8Ftq05CNjg z7|BDYJW8)mBGoDl5YwB`!X=IJQ{`kHXh@#AE9Zmx0NGO{m!bT8-F#ukfzD{G=G(^RM-3nLGBmH5oWp6M3Y|J)&RmMV`LqfAfv*Q)Irl zJF{H)wtEluGte5Q01KFSQ$KjzsJ=8nn68dQUQ($#zZO6Hzx;w+P;P_U{wh%Hh*-Z0 zpYG6_Zhs*1i63BQGQ7-w78jA7fNm#BGjN&|Se8N5NR7l+-bsaR8p0DW2?(8d-2AvZ zC0K6QF?hs&sew?A#0BTV?faMs-uZw#hCR+mAlG(NOLgdicZ8$~C49F|e>x)RM*RrY zi}voa)5PMK4tQ_B{ZW&Ij_30(ugJu>pH+){8=P*523|q^(=i2QD+gsfX=JMpWjyf# zXwc3hTRr2vLQtUP#ZLh@S?J7uo-Ksx+ zA-I?EZ(Hu7dL2yL&ow@NNvKBHug?!o3%r_F`At#tIBSm_uykV7rhMt={yOZPNde~t zdolS!HEVmjiLQKUE&>(ZBF<&MvN6EBc<*2$tJ~Z89!h7%?m_Bpke7KzZ@80hDe*EY zBM{#ELoa6oIk$9gq>}drAt2c5?PkxnBPqlDJ+eOv?SApGYbcK+z9_OXX9S%rvNDeK z&jg*6!2g@_Eu4_6r;g!jw3~rTo)z4J&3h7uPYua#$L)e!Jh?vy;I8Ziuy^_O$r86DUG38r`#+J;}bXEh?! ze<=%IE>=LYbAUD`=2-y%4#Bi&OcGFtYoHGEArsHQ3e1=rY4C z;B%B1^t$@q8A4l;*Ozq9V^qoTS36awCyF4asbc&o)j{hjQYHJIEI?Kz!EN`?)RT&o zyNvY?PWz{XktXW;)Kj(Tky^paH?L6;$tLPchbLC4w)+!BI&5a|@Z%xwC}n(|zRL{4 z^FoO1RIFmw-Deeppy@^o z3|&E#Cvt&sTO^-`A+ATLJAn-Tb9kpK9z8)=zCMoex3xkR$jDz>P#dQ$2hz! zK$uHUuw9YpwaP3|qYeT#eg~yl-F&$zZL_V!8qm1;nU&sL?bJ4>!A6Jii6eLHa`IAW zcbIh>Y%DaJw5#{FCNp&SH;f^TEG37>I;{}7S zD&j?K@E&{REPo%33YO|-h-C~UEXu$xu_R`)Vy{ zQRgV*$k>X-93CYz-pS4KL8uf9%6_LJ5wp0rW>M6&q{1B65lm;Q4_oS5%6#U{xs23v zPKr)*WEwshX8C9)^NMK zhDdysdB_~W+I{jxHY{6?wATebHvs+2SHUZ`F7}6|M&NEO94tu$M!$Y<5LjIJ7bYAM zo?3HKi{)st5%cc60hcfC@eWiuSCbGSam+Ux>_16MMyn#GyYAsr&hGA!My zE=4@J$S_GTCbJ^VAvfVO$P8*`cp&tWG9j03)?!HwbTx|XD+_GLDr5IpSW4(KX@mTp zIYqGt;RL$2Dw*)frY+Ls&Y0GWD=g65AbWO_uieMO>Q#p6&iw;-iQsdMm|nV6o=}Wi+#r3X9M#;!wC7vfs;atpLN3IEz-vO{(~A8)Zed=JhSm@|4#btLV3jSfHh9;4Z^9vF#&%?mm338iJ4|6U;o7 zw^Xn92@YlspX<>)v1`O6#E0bh!uH=K<#y{t9eOTck6R>9kyYugg)TT)7m_DA#+lHh zbl#Nc?@R4KOQ7&8FOIAQ!w2;iUY59$WqoF-b-QP>vMA+a5QX%RJ>AuFWr$@Cml1>> zQ9W1CF2+^pJ&TY$i;z8cm|(Z8No!s%fxGQ+Fj{bAyBn#H7LsQb&e_t&r7vpkEsCcI zXziY6@Dan7tWipcbWMkN%}dP7-_%CLKFX8*zso5&7<_t4$|Mkm~U3pxpTkQA>_T(wWg2gI*x4-7@^Tx3ILu8@C%`=2mw)rJ+4|_5f zC;TwkvanM525|#L>Q+G7Oq4;DK=|Y+={bJzO9R+f(mjJgHTnI}qZLlk*ayVIMXT`Yxr}keZQh$n$ihKDoyHCcdaA&X| z4sLPgeR>Ii8ADtBaK9*ZCWFA|X%xv*#x~*9=jc6b2rOfuBjqLf-Fm*(R31Td;MH6n z9wspVghdpVrFu%<^4Ee2E^i{Q$y}>%Elvqw3^s2Y1bp&77BSkX-CR;t&5uMhb6zVuFZH>`C-gh147g1MK_ zLlL<3_Vhl(3Ng{^km{RLUIe@$q#Y(zG~D*E&^+MBR$j z$8(mCz5op?IrzvgVNB+6Oo#i%zeN9%UIMC3bOAwRwiNrEZEvRi177SnKMw@0Ky>|1 z+D_wYGe_9D^DPcDr_xc@Wo7trl_+pU`n?Z_>_nD?_m(gF_n<3FyyCF(Hn!V>=Y|r5 z{lQm;*dW)f0DO9J&I{quj>Q*-&&(voUNzq;Kir;8nii$sSW0rsraj6vsC#i8moGfg zR2}{jr6*3lOv+bwxte(n>0(?E>#C^WD;7tJLC z%W`RP(r8~*d&j!bxSRdncr22#9|XoZLAuv8 zoHo2i+rOn{*fZ>zlXI8V4Vf#TUrpg;8w1-Z!Nh5|M^a?LF|P5kzTq5zLnRTNG3*j- z{q1wOQx>GuP`LW#~ z^Oq}E-~@~VeyQ{JvEoluja+N<%<|4!1(m^J^* zxFf|M@LIn2yT`v^MtzqimVFJAN}ecSmwgVCqTaNZ!W`&IpBhB#{Hz8OkBNBzKNAsZ z5i`^7!!V);s-_aEhpkP7uqG26OxjWY!S_h}gM1v=k9%s#wsXodFOr`doOonqL>7P^ zAt8=8QB2@MDdrqZ;1y3=K)pJxjiQ<$vmy*8yDyL7jE@xBvyP8F`Pcs`1tkJ&lvGxj^fi%zi zKU5ZtWNrttHNTq&ib5-+WdRB^H3lF#9Dbf4+?EJihJ2>;^hr? zbv2Fg5odz_91s(L*7lc!2@JOU-b_w>GxbGQod7<&b1Tyv^VYp1_JpAITZ}QFlzaav zko0l%kN-goAQ>NOlb@ncvgr08f!v!VY-wab>HKpl04Avf#EU|mr1Jn?Ea%PWL*U;@ znn_lMZ(J5}f3KgoRmA4I^DXw|M9kQ+-O<@j#Mbu=@thdp$VpNG9m`EDDNGWmHc|et z!qLumx<3O8ToOAuD%`BpZ2?5oCN*g@;8R`d1qC~m@95J&wtOllENf!z2bQY(mjO-f z`v?99od6yAHhlo-LA{L<;Og^E&*9IxUFu@bM|2=%J{v$Q;TTf9=ZRzUQMu`f_yMfF!$VUL5F4)l`fClyB>X*E`TE?tSYwGl%>{uZ;ArIWP!VwT~rNo+HV{T08sMH0+OU@b==E zPOp~v=x=#mkR~tx%zkvt&;7C9I!oLt@pSnI_7MXJgq5J|d+k~J;!Iw~f8D~lhDiia zo21A3ezFfRMU;j0z?m`w@cO%LO8_|vNgU4X<=QZr)e-!@*E_3r?8(aye>_PGc8!0k z9Ot7m@CnJmdJ2}rfkJ@wfT;~sY<=~dICROlUjZyE z(-VUTK)L?Cw=ewiypce&8S3W+rrhK!J#?ho;G8rQ^^*1hvPXf!cR$1gPU$wohe^$v z`gtWtSBq6;95W=}w)<=Krl@wSdC4q5TzPrcU-O;)!kEs-#R~WPDV;byYWWg*TK(ji@ znRtj-sn9Ov>XP{Bm!;Od+S>? zl@FQ`Yk-iKWu65W<6y=cjEJ=&H;!?J$)D_q6A`auKmXW$-dTU7&6T~VxqwvRrl zSEsbzHsWNq=e>Xc~pjBZB$sL z;V+jlo46e5)@8as`V~SWdCrx|wrZ{3(pQE~RnyNxd>+{=f3M3Y`6ov|TS#bedPsd` zlTy}`<;%<0o7-{idcAUgS?-@%rq>W26NWaMp-(5258I4XPqI(%?)3RTNBBHFC@iq; zQjrM!A6wr6)AeS}*U*s? zvPuUj(n62a&=CR&Awa$fZu|e9?|GO>xp(H?bI$v|=iDKgq~GxiL-Y=9f8#<)b|8sK zitpi9P(&|!f_>`qMI2nNn@wG`YO zZYY%#Us_l^Ik@*sLDd+=f2u!QOK#ENW!15E{yW$NWqqxE`#ynXD{fC#_OsEWk@3dD z>bggRUKH_2%7tq(g4i63F;yZyt3Uy`2Zmu&Hv((-tioa|9bRUpjynDFNYouAmt6gn zurM%6OB_&<_u7BfB_Ko+{JyXahp*}6HPk1<5^lods!jRvO_8V2jzu&c3?Ju*Y)Vxj8 zDkVC*nS)RkBZzs=*|I;%De?K-|@I3mpC0;N*+H*sjyvc${r5(++E#aT`8F_ zvC`Q3mbdG$$G$*y*qbHp8ON154AdVqhc{0UBVVf17jhgKSJU+3RZTZv@xH=*`_yVM zi|yUnHTO;^^X~c3v4Ic>AUDz+gZPj4eUK0eNXU?}rDYJ_m3s_JkS_Z`J|qhnHi%Z3 z=|UD)YhLV`uN%y~iT9QN!052IvmsHkVUg(2;k(_BpLLwH@mn<_&|;B4&=afaLulyB z4+#fNqt_^mDHOKN@M`oWwzZlh&helsBo3O8HaQBO+59nn9eX+emX6jM|5d}4=CGb(w+bkS*T$Iq?)xY!1%-{`mAO*amSPne*5)~BTSKE|pJ zUds(ovO#FcQBYh?+XNiPd%|MGwnfEYpOAy`>(>fwqz7*Cho}S;Z9v#;!JMeh%BLp#9 zrmPocsIDCAgp${E^tYvz%P2#+zPr*}M*0#0e2?qOlTkUjJ~7VUzFcsP{PIYyuEJ)! z`8Zq13>^?5{7hm%H9!JZHe7|AA0-OgVEhz*bDpFl^Ne_9U3S`RPcqxH*VB;;e2o&y zBI*_VY7>~)T`APwS!sb4?jfWVV6)a55A6CY-O3EE*1FZ#weLBgBr@&kLC z#&GA?@NMbADqmmxC)Zf8Jo)-s=UQd$=5>?e#0F;+ZfVYZ@YqoVZ8PTes>?B8)9*NU zZ?tJr8uvhw@+@ud5;F=?;7(~Kpt)mJ_t#h-ArzZ92$2sBkTZDIuOp{3^z)UG)fOeB zarI-EHCQ1N;G8KN;0!0aZ>C23ix_kpeW=-u++Bx= ztya)19l(V9V~h^bw%-~ea*|<8OVb>}8EbX>d-z&6XZ=}<#x*lS$+M@z8RSS^=|vJRi>;JApr z+Om5%xYABttq=Or{ufya@igQquaIQiKHBbO?$lycU%ag?0lua~ z+ESOHz$;%=1_TrcjzZPGA9{^v5^tm7qlbfESB;OWG*&aZaEU{cD@K+Zg`O1hyGN`2 zRSr3hu^zP%x1VtA3OXDG(wUo~^M6=~kS1YwySAzdarF&^xCUp9o=86P!_~zp0UD=z zALG{9>tzZamt+hF-CRin4+8GjKKbpeNYvnr+9>`WY<@cn&{0^r=Bt$`zimu20__Hq z+d6c6i?M4Y?rn3_Ev!JSSK|F6hH;&Ga=Bq)1eNdL?V0ZZR^vUTvx%cQ$(Pt>>)z%v zf9<;{LDTj5%@~UyQ&-oQ=+#@jiuQk&J@1V+sW_JqGMuKY5c!tDloQZIx>`X>R&Po#ncu=vE~!c)ly}{;5|CF{yht^HH*D%xdFm z&T$!U7Zg)MJ!oT6dCHB|*mLUDXrpqR&YBp9Ehw6VR-fwXJzE(Myf3b{77e`brwhD4 z@ur%stJm3@$mtu!{&3>`f(pc&`c%p9LRW84r5w;5rPj|?e=h~N>7p9))`n_KEwdWU zxYoKEH~pYx4t?|#(;gqtt3O)%X8pJtfiZ?=#WaT_YU*nn{K3x6WG!J^RkterrMtPJ z^bwve7l9YwO3Gf{$A2IDrK4TVSt3YWJlv9@|Jw&NeKWbxmnm^wJsoDN98P-^DQg6-8Y!J*%lKD!D>&_+!q&9>z^0x#}F2t-W@2AAGnyh|V9;PNbT!M46+ zEUrgZ%K5V^C?-|Q8mf79+?<*Dx_ zl@+(-v7~sTu{$t;p;WE7#@hYSZ?fT@iaQEh5mqAHbWBx%6)?4GjxSZ+Q4nc&1(4BeJK0;6Ow&Pj@&COmJpKC}JS*T4`Uq(Bl+-*S6$b=~ z#?}9NSMO5AwWT(}(X>bp5P7QUV$<1ISIO5_XmYNqfjN6EQ(}|{_9v)oYA%*Sgm5|;zjNObK=6gVR?!J8fiu-ccWo7F~ z%l%v-HPSA9izxgve*F>c9!P#IdD*XB`oKCZF|=>a>y^@l%}9Z8 zRJ)3RdmmlMRX(m9=VFLeN=V%*Tu>FXn8wTZ*U_63<-iXKr=X`3{U7YlR-fyP=?!nY z)6>`M^e{{Al3x}Knsrt8SY`ZGkDTNsZfVV=k|&cY3KqUYOmR1wgq5oAhiiIT!o*#A z1I^RKbvzW(oXV4Uh2NT2GNV^5jj=~(pm%CSr>fnJ?=56?mVO*QUj77DfQY@|FrnYn zz4PW?U~t=IjhzCk&Um>vxjL3JUPG;F*}1P2w|G^OVdhBTsCs4CO$!aS7tdbByJKQL zKC$OOKQD1@9h8N|Jc(czz8{oo2oZcMyunDA(PEe6-!Ln~_6%u(8k;QjKf_z49ue#Z z9o9wVYodf$4TWtq)|805-oLpsho5`8>G{xgXpb>!hon$3jAIg>=lHs~RiW%k%E=Tc zbz>||a5#TW_Vl@9x1-h_db^?B%!)vg3FUe!mEQyJyrJ+cW>k|H>2IM2A;r0}7O@zANpru!$Aa z!Af;?toJq_Ix+S1e#SpBg}cbxHwxXhh__FH>bU$$UmyPC9Pq*RCv1o@ea=XZLWwANhsEMR#6GpT3(DHotOyfa2wV zjdEM=8bD~>IL!$Sqa$FU-Q=uvOF=Z#}kuXB3I&u}cu(P5Z&)Prr+DyK* z;L7F6OYix9SM1JT*4J&Nd)!~F#?E7W$yX*PXxAjhkkh6-ig0c)TdiGzclbSzT!gi3 z*Ka$T+;Z<0n07R8CKn3*=;DH%?ILmGyUZ2*IJ>U!$Lmz;n|{|*@ssYl&^@i{$J2G% zy70=3MTx)IuIciA&+-62Ct}!Df1u!D2l0sBjqCQ}qEGn8 zKAGnzjPho`Zm0Up%mAg+Du4-AQ(>|~&=wmYG+kG_5 z?BJ-HUQvKI?i3wnw(7Klw%#!NlKp*~H!WTPAHc3n zuux)mxOXOjfEj+!-?#*c`k)qMag`xP2i7B*!EU(rRdOL#=0ZWKu1Wa2I9lm7T02g+ z$?uw3@y`WaHO~tvLXejP?)_M&PZMv5Tem!P86W+UByYKF3HIHTMZ>Gua1$jgEsw$* zWkBC!-6zM&Pc7G5+NhvFkV~M4=wYi$+Y(boLv8ePW9Lp-$<&`2r|)>9FDPvWlP}hD z7=DBd4%UeEiR?R;Cvp)V5B$22p&;iLj1*lk=k~6Gd?~uPuGSe(R_BrBYKhd9Q|)?D z>1C42dVH2_HS}aQGHHSRwvEdE&EoYDmnuhrk*3VLSOYx{`vOOqb%{8qilS2)Su7c} zI+7eOiL$%*-02=jytYYIj!;f0rL(Yx<>Cr|ykC;xYNoZYPC%b-=oAc~3|Sw!nPLS> z=<30{xz}in(HlGt^WZR*xASFv5VOn5eqn)zHS^ZHwq$#3^R(#4PQMbR z$dISq;hvqHnZZ6z8xFlI23IcQqQv6qj=Dm82J;ocOwkGl50@=exnnZyg$hi;q9Y~^ zTHR-&L?4A`qA$Wy#o@;z1MYsFA)1^N>4D&f5!6weqZMu#8OoulihSGu>^RN<`A zU`zhWzbLV$xALm|;`_cbP~f9pRWNbKe_3ZlD0AWhD|iMk>_N&2CoRP4Bs|y=bPX}C z>ATWFTb3DhMHL0o!3fo$C$f}LdZQ)PpZxMmk-2Q{8MS$y%(`1~x$uq!KVDP#(5~N3 zw%MtqH#be3FSD54*BB~`Vv~4ggib4S=Vzr~x>ywXZO=Vaw*$3C+|eBl!k>{#GYdc{ z9d|pHMj?~PtUHpn0&KcS#vR6T!;9~|-Wtl}n6KPq+ZjKgVcki|zp!JYnxrLfwRd~O zSgSI~q%bQ36VrBMA%5`1rH{`lX=0Bar9MN^u%aYB-88-4h?M=~Uf;Vo4E(a9Ti9jA zK#2xq*o7FY$n(I)2^BP+>%5|x;8V#R#q(P5y|p^0#s%Y#Zx)Q1HAFM4Z*|?{7W-B_ z&6%ud2GY30g<$69LZ}{u-SoXA0an{QP13hhjG8jN@MghTPfh&mxfr`;plwm_%EJ0f zD;`CsK|2iCsq_=*V^-K<{3WegajjJGI7}>zMP*W+S%x8@EW>)4Yt%-8(sY;RO23oi z(;IJnbJixqFXcevIr*9zhQ$rJXhyH0Z#7x1YT^0ln6mhfs^ zGPYN*JF5Y^vFKd2sqL+*E-hA+yZC|8ofB((PbX)HPPR8RJ(e&g{^PvaeX&QIYRXSw zUF@ua4j(cnKB`4>q8^}hJEIMm+&mc1s{Ho;iNZ%*RApU-eo^k;_MX;S`<mDtOB{rbVHX(5Ni5BK6e4|{q?gw-x$wY zdHndieDj`+nsk}yjtC#{(O?&Ap}X*cW$DhcCQR-sEcr+(so0C_Z{7$joxbF=X8a?yI66_(d{O8sk3N~ ze}pc72zrtUVX=gxgB3J?3H= zm+AYPCk-W)J)=Ncj|$^qF3DLp_^s=9%spIqsf`9P|629 zNaxX&B4n!J1$(mg_aaTYvQz97X0E2GdiMR{5h`0G6ltHNBffyi5?Ar#T;a({j4@Xc z2g>;DgC6ySCjyJyJq4w1F*d`7(p{qV#c9^eHBYrG->hPRq9z9Z$1cBpZs;oVV@h#B zAAeD4=xX7|8xgvN_WTA)enKmwkEP8W3Rqvc+)gje@~DlG3thiw9mxY_9iQ)H*CG5? z$rmFRy?)1wFwt0w`g;X zx*q%4T+B6UdHnE~E0_Ox_}k5u_=rbrnYsr0MWK%jo)q#MUx=CG)lk%(D$o~?FUryt z*DnfsG}5UX<)P9;-Ra#a9)ha$nBDpmF~wtI(%Ytf?{m3M#Cw-PY3-A6N#*;$3-#_c zDtMajkB<5t2Qm;`2e)#^$bGwm{BR|0Cp5QH*5)lpwC&E8YB*=VW{j1!u!rwata?LN z%A2)tk1FDHM|sWzuIZ_-Hdemc<8{p1BoE+g&UK5t4O@@4ine{*`f$o$suE20i2}^y7ylf^J9-5(0xEldF814p3)zh>mTtrM zEIsy^csrO>{eBI{+^8)=>}HW6mIue?L)Xsho1Q@xm)^~>yG7!D+jX4(_{gf@SaT4s z7Ky~?mqu2HAoXOASFRNci8_nvrzaCxUw#`rXqhnSG#Y(an}%FBg?c$9>-hcJ^&p0a z`)VP5u6_XXh={{+q0Nh=wBFXc%sK*X_Vvci7~yI6rx zx}po&KDtM$cjQL~!1i$p+sN~=?oU{Fw>(v!9Mvosv+!apnT<SrI!miGXtdCRFK9GyZw$6I6X|w$^ofM;;fw zDPYp$-TIDOvc}xncw{YW6!t2tVwQoY2rQh|7wzI_0jaN%G^t>)6dD=u8FG@VGqoBL za(+7KgsDMZP5pztd0p*dB0gzugKy6|I`@p<$mdb?`;uAheU5uV9AFS3q>!id&udR# zujIW!i+S<77#i9zfxT0cX#@XEx4b(1>scG?vEP2v-;K%C{#Z{dOsYtt%gp;&(jNR= zCe-xGn@n>Cy({iQLh3Z%7}~182x$dZ$K(v=4Ck!-W^5&2tXae$i2=u3#xw4HM@ypa ziyhAqdNBy83q6TtWr&Ykv-u4BupWk^YEd&#viSfGVd8shl#~NkvFvB*J`nlhOy0F9 zxuz)5uQ6l04jUfYi6GF*G+@hA%K48C~CR z6dS!3gOO|?)pW*W`2W2!i(yDwW?c z_6X3F=$CrF`@CX)dX({FpVDO#NRAzIkjfy*l@WQ^`Bn7caYQ60se=wFV?F;z-SAA_ zJ&@bMurjXg(s#*T5&j>H&$>dy%th_CUV}WKA1)kj-2r(Nf4Fd9e32CFa@u>|y{g6+ zuJbATPpKBvVHwC2_-4|Zux37y!`Wq38r$N1ch}lS;LC|Th!>aI`MOfOnFNaW8=u=Q z+m14h=E=~R7=4HE6sly9agZN~C*S$-0u_`yf!9_tp!#y(90-}w#wZ-lhcfBTS})g; zI+fAl^RRgyl`uae5s!AAA5={3mK2z23_}#fbF|3@=p5y_!Ii(qR!?ld#1pZ2G;LEv zv`DtM0pTs<6P$Q5^FHK$YBvdrjTC5Mdm$W9#1;x$`Z7?oCW7M|>t1tj(^@>7-UND# zgz6L}R`rUF=5|9jCHJSE_16c}nMc{LhwE^6N36hpo0v?<`++6wgZ60hCHfC-+a@Xr zcABhBwd+WYZFOa4%Gy&;X)wKXW~k1}uLcL|_0O>R2HV5)MPuwnBUPA)ZdZdtA)byE zI&b|S8NjyGakFLHzewlF7DL-gmyJ3Kh=b+V#F14wZ?R7JhwXoid3u zgo;m~U!e^*YF_ql{ZL>8XFoM+>o4O#&NU7+@WbDr3PTa>BKAWonH}Ad#YZNL;BT;B z_`c+asI#nPJ~GFa-s$U0m-arEpY#}XGB^xPN;j?aSdpKMACEcceq%};&ziO^-rLOo zq(v?)TM`?{PT9IxGjbq?IzU}56DdY6(XAC5CxR(n?79}cI{Nm-WF0G6+b>p&p5wVa zNG4JJsvtvre&p#QPs&IWMFln^sv;0Ml;k=BNn@CZEM7tz!P7)LIPqsE4vo6=Z;PEt zW_yXp@*=XnUJOru(i;%%?@oid(A}>D|1sb@a){~dVAu`4jb zXVF&2vd=cF+g;kYtfHOr!Dlk3_;-%<>QmcE>R9C_dQ$wz;UkN1PbO@EujlgWD$ZVB z!Jno$e5g^&W+V~)1YA;i0S!4HjX)aCjeO28**{(wt#mXPcLwoS8K76TpUazi;wlgx zPmNFu2VB9W#WObDzqNk8ns*7>WP<$U3^x-GKz_@!Z^rEoVER%n$_FbtdM}%`j56+q z#@!ngaGuARh4`BV@#7OjA$Qz=5!(+&cdfhqK|9n7pcBdA(X*n6-|7{*zwZYU#qbLMt)ce(N!4Qe8)zueNw(Gs~-VV$Yu5 zfc#61&Nt?Kt~u0=?N?1KVpWDD8U}#}Hp};$-UL*guaH@PJtjVUi*U{}MBMV17fwuX z#w5cOO6aqHr+FvBNp~suR>Zma-|5e(a?L@6I3v#Uaj{?fIQ#Cd;+hV9K9~8myj#L_ zxSQtL(Hi9 z`kk#}*Ks|{*L{W-?Pa?*1ijcFd~e0+WxpCe3_rMKdH8YnQb`#AXZ|m2Ovabl)v68} zb}i~n4y;;n;&sYg*wIdJ@g1e`i_8%voi5g%L0k@Etj37h&W{tpg)n{Iu!3_PHhFZA ztL=7fToZ5gL>q5jwQ0Di-L49g2fxUYJiWM4MM7(Pgp}WLT)32YF>ytbu+6H3a(Di?`ZPQkF+57y~ zQbemZe|OSK)>xgULHE<#r|qx^0S5(Ei}oYUJM-{n^LF=Mfys6g8_%ZKq8Sdx<0~(b zLVC)j_)jYG$Px3Q3lN8Q8!3$4^$(P#afXRihA`4bh*h^|gIk|WZqqdjk^BVj8#BV1 zf?Id5@Co5Ah;`SyJ?rEDP}3(`T4k~}rDxtD7l%}a>eXwPMnj5GW*d(`?+NgG^fNxI zYCeVXxj7C}L3P}@dPmGG`Dt=nx1b)7p`I2qvKM_XlW@?~I72KieM2Ud&zZM69@B)d z?M&H4%0g-&@LwRHe%LiUJ-!y-8#0gA0RjaM-`_iQ55e!GUKZ&=zxl*Xk$G{4!aFx{ zI2l5}Ncm&mC!-D%W4GtzyZNI<);r0mg}gElgxYiRXqS+&V%a1VNKBFLI30)0h)ud2 zhDl7hmu&Yia189*?m6o&ZAdhz*MO>z{@}CkA)Kq}sGff96DMj{yEw({R<~>Yav2i!z2=f0p{^UO3KZ+snHl%wH^c~(lpZFz3)Fu(9q-pB z;9IxGUr$-;K0BknxZ=MfpvP5#?-p&v3HT27#-Dy#>?Q=!teMd*turXDH8Tw>nR(}+ z{i+|BVwJZalmJJeoC{GiG!yQ8_=&Ywj{WI^_Wj0*H8|~SbsT}n?cnkU@+B=7NCRPv zJNy1N^sV_5m|M<+7Z}-|=2iyIWXqI4@}xPcA5sk1^!T2XLRTW1$EDhwH#QhOk6rED zo*af7ZEUbfueC%>bwxzTzPf!;@#{5}n}!T36^64KB?eM)H5cZ6R!?EpO$QpaUawu` zccE9JedhG=HB>6|PdNtK$xpGTFyN9uVaD2387V(2FTwOG?mBJT+HT- zp#u-odA|(K3I%;NbPZ-Sn6k7nV15zIzggZ83R*XL$2Ny!+$^tsv=wSlVqno`LUY?a zNpyZhUU@?eWoNje)Jz4Zae7#C?%!I>;vmrEgLd2oBuE^f^BY#Hm zM-yzUepOvw3TkhprUe@GyW#i7K-8aWfByR1w2J?$RPZ{x@D*rq{0lIV{(Rl%E-zdR zIk+AdO%qIRZE4Y)tC(fnUie|^>UJB9NW0el0T+yX@7{93)$$X~f=qu#Ksiyh_E)|h zMX002xtSZIUz-`5uFk92N>QR%VPr%r{RDULO4|!2O5Xa>82@Qg6 zRolgtx8kLrZ_pUXD#h9b13)jAC7CF)t944go zJJH*m7qbl?pG0itihsH{b2Q&|Q3YcNEi^|gV&7j$+E^T`bFI{qZ>_jkIT>b1Qlp(y1pE!(9i2}##WM4A%0xF6v9{2oIXri&siN;AE^r5@#l1XJj2o?o+gps z=c`M!=c}Oy75+VEsx^T-nv7`{^fz}hiSz#HJ2^xvNV(2g5>6=_pF^;LRAN_MS-ysE z(u`1eJ29TcKnJ4@B*uPG5iL)(Fm@slCv-n`Smz*PJ<~t1!%075w>b@4B)bCh+-a7% zLw_)nhSX#CIDU>}iQ_}*;8@~m(k+(#V|Q}4zLCVcV`tEKmUuo?0IrUoUIww1CRIqT zj-7zmZ5jCvl0BQBob1(o2Z@gV1P9m1P1o(vu;1@qrG1oR;r%mukjmHwv~V+cQ5}mo zIVBi$yWeAPZN|WN0NIH5?2c_#rOp8s*(b@bbHJVs(FLZOZjmj!0*vT~l5?gSH{DA< z8%=|P;MRbiNWj9qPb!P*TNo1W$^O!k%3kbDe)_Q7q@u5_(U!N-q9V{J0}NV)zXVuQ zhYvs5Yn|*J;`omIrO<#8I2Sne^w??gR+;Sb5y&E6cID_Kj=;X)Tytos5^kq21dE9(p#(?5R*_!QAXDh1wE z4Yvrs0XPv$bt14o3+x-)v3AlrtDf8YRIg+I2PQfPGtd*_=4@hSo*>Qs0F~-u{n!+zQvrhwQl$!EBYqY@fD=zbo{0L^ z{CiVuKb1Uod^G^DG&J2KF8)aMh~AX@PmV6}^y)AeBhEVq)SZX?Hsh#zH_ z{l5VwE8@6Lh!L4?@lv9Y!y}-JWZEmf%6EjT!2|4DrJ2Ug9i}cB?gehrLwQJH$u!^S z57PRG5^DhQn))~#B?=I`m~blg;KFHCU}GZjRPezUsICTg06=2*kRQU}R*GepaqZ@I zkaEc}mW^-%@4v1q1!M%Nkp@h#@W4xVZzE@Ql4^Gm1eiGhK)^Xar~f~#fT{5JKYRUe zhq~I)Vx6>~5~aKMmnOv)*#U_jG{XYg){hSZ%3ZFs0c2UM(f~t$F z`Nwc2pa}@wKTRiwDEh)*&QV1+9Y_!-QT@j)K+{v8>0jslbu18e06KnNx@(hEo%WQc zDmUO3V7{`zeAjdO?EcRj028Bu{sbAQ>stymbG!gP_@AHv9*TY+D}w;wIRPj=V8zda z0T>fC(uRHi4IiX3arxIhKz1Qs@a&yTywFcDtRoii){pd?+kGD+hK36fyKD2u|3xAd zMbc?hd366v!PtkJsh8(`>C_Gs_i!tB067Vu3d6jA;K@GwWDh7iK=2y?!8?2(lP7># z{-=P%@{3uu*R0F~#_a%r<9J0GBI@P~eD{(cdxv*hRg zAz5aKXi1#~?N-?k5NM#{>i0mb2_kx)Jx}Nx^r0p*W8XmwdauXw z2aaGGI{|t>Fp#P%Vof^ex?7|H;b17h06mB=L?*cYw%wE7-1|fFL4$>N73oX@7&GZSz?g>qj?1chJ8{42rM9*mgaMrP3`7ZA`>47o$TXQP)Ct*brk&P zgrCJpQ2~J8$XS|HBrTKR0bkJ@XwPm#Y%S*e5%lMSpbw z>Mb)M!L-b^Qh6kUrdHd3p8yWzB0|C_$%yyonSn~ES_yT`yGHvT+F{Agvz0X9nlj@ZnTftX1 z8?Za%qq-ynsH)vpcP}38X8Vo$Xd&(X(FgPO%v_{h*%d@;y}7^D(zWgBBc_i~9XPH_<+oE5I%8uVTZ_`52$b(2g1pF@qCAIChH8;~CyqzZ z{m7<_euq@(nxPMi>K}RuY!89$6tM9}_3KsPqGiCHxME;{JwQ^k>|s*K5ac!w>kJzN|wF z+jore9T%|k7nZ83R6nHKsc!Ps=qy5eBhrDgCe#0DJqB1&0BM{f9OU8!97D)Hyj<1t zXv;2_SQSIkv&8`3@vQ@@x$sm8kXyzuJl^6y2yiX%DBrlGf`n#cY5?C+YuB7jDqyq# zqTc}Ux{)(lcLFDXB`4}@YJ$T83yGg(AQ(ML8$SLC(w`(9t&5#Nu*C%%{9U%#Hv_Ls zukeXu&8>b4B~Zly=gpLzN|BdyTjk@qU_$z+e zt8l6qDEjVe&jED&E6g?M$*VMr|8UO)t8EWdgY@3qe{~1&uSzKAb^Xa<^^JaQdqAPd z02zNwxBgt){U7; zU&QtCzXE&WK)?*|6ElGBCrP0;)`VjUlqSkG6R)lOf;ewb01aIN z1HyGe^q<(LmP^AV!1;%O0-eP3#4kUx|7J@K2VnTVCp)@t9;kBu$rC`=J_nk`*^a-$ zYF-_zDtml6vM%-pL}cQpR{nJ9V|I3}pJgfGqg>@r=n!<*{MG;m0%HSJ8M&&ingCup z?wEq`ji5PQb&tGsk0Ki>uEa_8Jupy~0rSNlasz_%icfq7z+x;=i=nC02BLl<`9R`2 zpgK~h6psJ^_%k_^$AO}C+e`Ok-ip3HGJwR^0J>{lt@<}`ikeaNp2uSEPh%!}C`(KM;QOw5o?w!vYi}GgA{3`?;Khjhq7u+AL6-qkvyp`tTU)3&R{=sp z1)=;&j3$u(hk4ZCK5jl>qsR?7ncJmesHKOty+r^}HKN(#z{fOTaKP>-uwNQmoE>F> zB7F9i4nJ7MH%u>Mci%fUAhKY;tOLEa-QAyj6{NGudZJsKEkJmnKQ+yL^4|onQHsav z00{b-6vwsg(Ey)ofu$-MIE=ce`d_?J0MYu3V|ajH2Y?m+)XPI-fDHYUe1OysgqIx% zF9+aiK)MdmJb;Ve=$3pss2g#UvDbNh4z;jkL_lOde3Kr8_Tt&Nq51coia*}>QW^&0!va%w$L1cAIV zLka?VMa_!<9~NhH>VXNZB3%OBkpa};H~Sj_o&*4Mo%kuFqgDU4^5^oE)9tM_VB}vk zEY(aKhHsqIEq~Q*Kd+Vz2>&cpOk6PKF4{m2Tm!0?F#x!0KvDXSZco%vSBbajH?C5b zT&puwr3YfbS0i7524grazX>My+J0b`@$*-Wl;jd~w#nCDPH(VR>2lmmD{m`VncHjd zOLsQ!pmrM@ng9AJ7`PFW7t#MjUfE~rjPG-aofV&P+*~18CieLiw~-%$I9 zkC=ppZPoZ-w{%zYm#MePVxm@69?{L(if9qQlONdPRIxuPavcW%xamJtXbly5Qovg6 zuL~t|mBDBJ6+yz%=<$c?fC|h%iGB@OdiMi_`O-?wlP61XDnVS=4wW;|oj;Md(J?bP z5uiSoDSNVBqFxrIR<=KSPmZDHR_f}9+J+jIp$t+*^duRy*u0Njt)ninsE70c(vo!t zPyyg-5aR!^fSP}M{>s1U!}|g!N?mv)tW8B1koNy3=E({jNU%14UlvFK_%T~_BHF;^ zm719m>UcmN0PGQ`DzLWwe`M;fM3O1{EETwFbj~JgvQxi+o^v=SLogt>sdg?cw3xqH zZ@VQlQs7`Ie*xJg(vOV^xKF`LY}Kxe6Xt4*C*jBq;-vhjgr0P{o8w|@_hNjVQN&B) zkQcfY@(1hGF=#`wc57nx9o6$6}6FR~$LwcmilAl|^cP`>&gWL14+s0dloT-KnJ z-<)2yxvQIB2ijP^UxZJTk@S$y!@upb^UlDKOw*0L%qK~OedEGT4Iaz7)49;Z3^TfQ z(L4>SM3%<;-s+yEt9~Assz%{;KVOVPL-W*LY1x+NQKkdgxzW3LLn3GLcv{69R58gs zea*A6XtJ)cbTwhdbGR+o#x#l>`e!4He)v}CSco}^jjIz^X+o*$_^x9`3e4cFT~G$Xl=uso_K7v z#pNJUa`bA$p=RU2W3>v3I8A27+C4(J9|$hvr{$3Zk^{mED&K@VkONQPKcX^b)>=@< z6_~fpPq6LHxy{9EZcvK`Vi3v#OAbU$?iQ~Q70}lYj_R=)d*o4s5g2`3dEl@X@R*`` zbmoX-l@fdmxil8=J??elr6#BEw5P9MYJd%#4wSffFrJCM=x6ts`1yziA?-8!olK)M zg`0o$oavYqvYEe zrXcXgy~g-St?ewX2)Cv49&s~w!RdBFU+@C zSw8ULPkT%G#oKNFPSGK&f%!#?OX!RF?=VUXa5ml`Y>@hXrl;G!m6Y6}w7*bOq#5u7 zD;G)nR?9IdH~ez)-enc8>@RJUxVWsYyZEfK`k&t0`#ra>jiuXnHfWeMTQ(f#VzK(> zhs)}hA5ZOV$C6SQ;Tb7x@br|c@YEC*I3nfxaa;Z@~6S|S(gcRxN( zXy%T~7on9K)XI{F`7*^c-&#*?7QLur!PuUMq*Kj7o>$F7Uh2q4GiqyET-SaS07^@1 zmQPDCzx;8x+r{vp-NpGJ&&Be9Jj=4e@s_j_{N>}W&KH{%&DBs3+;IGgaG}GHnV!ZV zGzYk=L7uZ3Cf8XVlRuh6lfS9H73+6bj=L=&8jZ0L>%W+_Rqh+okPkQ6)l^L z+)m>O^X#_f6WjFC2=kfQ*Z92=JNWh!wpHMA9kz+#p65hwh<8TwjqP!(ErllBBrB<6 zZu`3XVQg+qNPchA^=;Ms<6pLmX-bvS$W8?38zIY#2bP9wooL^Mv#lUHpBt`!o>^xb zNu4i_^l27He(l=;0YA+aE?IH(?TpAx;Q|}zz|^(YSJ$1COB!52^Cf65TibZaAQ#G$ zw7o3t?Qi!&3I;EeHeKyn6B7suvR54{r)f7#wKqTb47?75MOaVyv(4LtMoxA5)Xts9 zI4l(W8ZzC!V`#w!V%VVZEDk0vr10rHPlNt`%Nbg;m9s||Y*s%i*@Q0@mhyZ!-)gRLL7`H`^Qk+m^mf`b!jab9K-`$!awB4#xq zxFF=&bPyB3GSoDbq=WDG=M89E6gf8CVnM9HtoPBFqa!;%ME$-09wYNG$^^tb!JCy$1bwT`fSY@j__=ZjF#1yZ1^47S{& za1<&}6052VY!1>4HW<3Bcl`ydbm+jbsrpUw2S3<>pFvil1zX6|jV6&Pr9>`~l!LYr z5%S0FqT=lv?$fxAURtFL&nw)-t<;+qzv1(L-Y#YAoG`jwTWS!MjOACvchZ^NlKr-$jU)D z3c9@vj1RTidD{}TpHG$eJhp2;%|O$e8Z>gyZ$-XSihn!GTp!|U(PngAw7F#ey3KLP zC(Z52(9^qoaBy4Xi*_`B*;DCAE~82q_Id3V`&U8~%Q(9S*W~1V+v0Z3;UuKJrfQA% z6Q~YMYmYs&HbZx&y}lv59#J1Ik69^WP_=0FxjEMda=d+y{o`1}gk;TxIKtRzwSciR z?X^+<9?CmnZs$pHlts~@YTa^EDDrl5$S3zUaD<(|YDLZ5Mv>2!HY0e$EPn>!pGOp) z;-3fsA+a)Rb}4(S+EvXy3lQ<0X^PcC$Bksr8aQ%_yg;`+y|yrF%!*}BPDfBOIxm9X zBIgH`q;|%+_US0QmmMu!TJ2l$!^wum^Y`xA?)<1q zq72%tY0IBVMwjjH_76cK6k0(fpN0O6LxXU{8=pBi>yT4SGmCy>>BQBt#eFCP1>UP4 z)?_N6DHZ72HH`1KH~+#cN+%4zWCq>SZ|DK$IW*X7<43Ko3Va;4(81#1#@UaU7!xa>$! zpF{P}a$!nB)(ocJWU09?j5^T8QSi5nPrJU>=1sc>hV=_|AuVP8^xLr-^51&}GA5M* z{8r%^Q;CvO8*#hioX?~wE=Z*5pup4DhhZAt(y43uoSR5Oibf+Rq2c4%ZFgkirmFAs zpXPR3O(ra;Z1#5rpkZS0QNQyvE=7kJxz!zXGk_NUV7u&x-S%rce7bSnz0itG@9&@p zr9(__*sEzqFE=uJW1*+B&TwIEKRksObxSpUqn>>{1UV%lgF%V&r5&x<^JU5TS`N!x z2OnuEfjlSbL%_$Qf~{;?*AdePS4T5b_we7Jgax8&m`Kf9VaQeWu}|x!FF8mfxglHT zjc@Fl)+Jgu-8WTat@@NgwtCGYrR@9MK}cjM$jBGnO2}u9AThRkJlIPY0B%~C8lu75 z9KJs|xG|*@JEN=-phS)-9-leZdbk_peppomHCpB?BwxSV9vYxzU0UhRG|9=H#h)Kn z)UVid-s$j8|2~nu@fN;^9d+4gp06g|+ti}xDJqT2=vhBP0D)q6YDT10;mPgEJ<@BP zi>#DGg<1@~=5ZK1oUSACAfTgPdY!`VyKbjqKA7I$(l!k~Ixq|EjJ7!X+DSK0LM_6t zUOs|*eyP!-_+c7ootnLQu=xA%*(o)!U3$^h_)JQtnN#v7Jlzl{izp{s_XD~LR*J^E z(8m#8sZpwqEEBg3gSN~Yyg2pWF&taG^Qs#-?}`~X zQvniW^Lx7)()e!rcXE*2@AMbtF4JE?UH*_oKet?deJ=3<+o&|tJ+}6@@RyOwn!!pB z0$PAjD|7{~VU-3!~VU4EaV|MIexBPj5407Lt& zGTPu<$5Qui%3q;VeZ~=?;4kQZW}9#JWh-AxMF=u@{xVIz_QNSY@n2olR;_{0CF)%c z&ec|$k`%w}>SHfD7c#sO!lh?-b2HKYp{$TN@V(e!;}BeapJJ1!r|{gwFbVj^iLk<< zxjpaPbm4diF=uHTFpVYs)X?OaCjBI+tsqN(9 z_>fdxBd+87oq+LXXHLD4(a(iEY`k%g?I0JT zQlf)=kOzJtb5RW&N>FI^kP?Bh^v5)_ZRhRYXw4t=z6FnKrrn<3oelvF5^o*L!N4#0 z@vyI2TzN{o_?r{PtscuUB+eIgUt2;NZQ)^Ka`@YG?8$pfdVxuFa$+pMLv1n?*3*5j zkW7G{vEw0xjF6Rbqb26n=489*LZ#NV7~cq_25=84Nx5rW@ifGu;ti&+LZy`^+AQ?__!+Zp-vWd^ghv zbKgTuhd*cbLi>Hhbl9G$L;Ej?>G0P~KeRtUOyl>T_ec99#B}&uW+2)hBjQQO3`T69 z9fH^)I}EX7b~s|E>`27g?EZ**W=A3Jl|2ZtZ+0|defD6i&>s=cUUn?n0}<2Vi0q+= zU&%Hg9+f>D@#yRkh{tEYf-xr`ro)NZqY=kvk42o2Js$C-?1|_-88IDB$xcA~RK#>> z%$|%mHG3-JwCrh!=VT|M_v?uGn$1o|`#eNE?b*}Oo`IMS7i7;s`$EKYn3-)vdlq6k z%+5|j8y`QQJvVz6+Vc?8;iBw0h~LPbi_Cn)bcnO(qrCtTuW$AO#H+G15wFh9M!YUN z7rjdm)8X6Mix8J)=ObR9U4Z;D#B^AmU5NG#i0Sa1>?Me|XD>y(Bin?yHhTqn??S|T zOZG~%??%LXOZIBSb=hkXf1JGz@saGe5g*H5k1-n%@%&_$qx}S8I{YlV0`V8w8xc2W zZ$^9}y9)7@?5!B{OT={eZT2?A-(_z{d^@`aaa;CI^!@=6?+Mwv_&j9qM*KK?FXAWJ z`_UV6_oH2z`#xg3+=Ga__h-V}B0^)?+ONb}sUP1h7 z?p5@jhKMI2_bbHdxi=8c%56bBH}@u=1jKZ>HuoF8M!DZ1F3D}>Ym|Ejae3|!h_~hb z#8)Ku9$%5%`-peu{(`w{5%F%H`vCFo+(*dVgNXO}+{cLb=l+iPK<*R7@8gRbe`e(} zh!5s+h!5q;5r3G=BmOAYHjTf_f{52K*ADF;BjR<;wMY9=#B^xRbwqqNSB3b~Tqnfm za$OLAk?V#rn-TFk=DH)kl-mvQ<=h^KujG0n{xa7a@zq=(#Mg3rA^s{?hgq*9ro$V# zeuyo(f6{j4@of}WcqGfalCAiNojb8(J0T|~K9dv@;y8BVTn@2KxPl|gYg<^B97#@M zD6~K+l(Q6CO2ZktkcK)Fg=O1TP@Bc=3vZ=Wo!Ru1%!=J%WLz4y)R z>}Yo8&9Sr2fxv%c9t3 zH?U3%0GDdLzUixu;CHq2!JG($ zhtVzoeqZ}3n3I9x3oQA{tR@gx3!mnf7MgXWDyUJ_o|%X&(Uh zX&-_4HxRQR?PK8A+NWTY{wZ{a{uwYs{{oB)=v0~dKA^6D1;!0@Dv$m(Fk5$IIFuI% zKdEN`bM;Ixc|eS$x(+PRJzxrf7*+Lb;5dC0nDIc&uk>8tBt0L@WFY3@dI7Ll9|LA8 z5Z+ZE2Q1Sk0BiM0!1?+V-~zoExKJ+vF4D`8elZZUCVe`vPM-m0DG)tEp9O5t=YVMh zqIc*A0-N-Mz^nwKcjy(sHF_0rlU@V#>GOdd`a+;zKN#4pFGBhrpi>3(LxH_|9he{x z-dL{(hV=$8{XlqTeK|0yH-U)(F*@t3fLrx7V7374ojS#JS;Pj3VB zeV|jFtZx9GsvimbnSM0zB7Gz9=XyKvV%-P4RQCgK)eYcndN=TPJpjBz?*-ni_aV1? zfN1S{7}zM!7~d{I9UxJUmU((eVLJ?kd}U)4_q zeyE=Y{763?_)q;uz>oE_fS>8-ApPe+v^xDf;6D9)V2=9&V6OY8z&!Uwzc7UI4XIKh26n2A8N5cie9DekL)^W0YhE8N!tE8W)vYuz^j=evK2^b3G!74BPr z2fJ?ra|jSE#C-?wQ1?zSOMqx0?z@5Y?t8&31EPhv?*}e-KLBP05G}<0AaIrYAuy|f zXd&*0fk(L?1s?5w9C(cTN#G{;ZeY;;G_cS83^3&WJuu>ao}Q-rMd0_{f261B-UB?v z{W3jM_p89u+^+$D=zaruy8A8Q8Sb}%KXU&Sc&7Uu;92f>foHql1770(fS$PfBjA

    vncc6C2Z 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�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 Tgcyhz_#+Dx3TrdO20r~i7_9N? diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg.meta deleted file mode 100644 index b846aa17545..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/Google.Protobuf.3.21.9.nupkg.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: ae6c2b051853d83cb9e85a527f516a08 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib.meta deleted file mode 100644 index 0f82551b67a..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f9615e64ff20e6cefb896b5e3502f055 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45.meta deleted file mode 100644 index 5e20f583809..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 385903b30e115d7a58617f6f0fdb6dad -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll deleted file mode 100644 index f73a17baa4610612640c7c685e039f9e4ff8b491..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410904 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�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 l-W(tbGcx+_rv@&*JH3;yJ=jDN)*|%Qguw0v599 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

    O^hcQ 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 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll.meta deleted file mode 100644 index 7dc44b927e4..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: 4a7b5f56be0f0aa64828fa42c1289fb4 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml deleted file mode 100644 index 4d6183a633f..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml +++ /dev/null @@ -1,10465 +0,0 @@ - - - - Google.Protobuf - - - -

    - Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy - - - - - The threshold above which you should use Buffer.BlockCopy rather than ByteArray.Copy - - - - - Determines which copy routine to use based on the number of bytes to be copied. - - - - - Reverses the order of bytes in the array - - - - - Immutable array of bytes. - - - - - Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. - - - - - Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. - This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical - in .NET Framework. - - - - - Constructs a new ByteString from the given memory. The memory is - *not* copied, and must not be modified after this constructor is called. - - - - - Returns an empty ByteString. - - - - - Returns the length of this ByteString in bytes. - - - - - Returns true if this byte string is empty, false otherwise. - - - - - Provides read-only access to the data of this . - No data is copied so this is the most efficient way of accessing. - - - - - Provides read-only access to the data of this . - No data is copied so this is the most efficient way of accessing. - - - - - Converts this into a byte array. - - The data is copied - changes to the returned array will not be reflected in this ByteString. - A byte array with the same data as this ByteString. - - - - Converts this into a standard base64 representation. - - A base64 representation of this ByteString. - - - - Constructs a from the Base64 Encoded String. - - - - - Constructs a from data in the given stream, synchronously. - - If successful, will be read completely, from the position - at the start of the call. - The stream to copy into a ByteString. - A ByteString with content read from the given stream. - - - - Constructs a from data in the given stream, asynchronously. - - If successful, will be read completely, from the position - at the start of the call. - The stream to copy into a ByteString. - The cancellation token to use when reading from the stream, if any. - A ByteString with content read from the given stream. - - - - Constructs a from the given array. The contents - are copied, so further modifications to the array will not - be reflected in the returned ByteString. - This method can also be invoked in ByteString.CopyFrom(0xaa, 0xbb, ...) form - which is primarily useful for testing. - - - - - Constructs a from a portion of a byte array. - - - - - Constructs a from a read only span. The contents - are copied, so further modifications to the span will not - be reflected in the returned . - - - - - Creates a new by encoding the specified text with - the given encoding. - - - - - Creates a new by encoding the specified text in UTF-8. - - - - - Returns the byte at the given index. - - - - - Converts this into a string by applying the given encoding. - - - This method should only be used to convert binary data which was the result of encoding - text with the given encoding. - - The encoding to use to decode the binary data into text. - The result of decoding the binary data with the given decoding. - - - - Converts this into a string by applying the UTF-8 encoding. - - - This method should only be used to convert binary data which was the result of encoding - text with UTF-8. - - The result of decoding the binary data with the given decoding. - - - - Returns an iterator over the bytes in this . - - An iterator over the bytes in this object. - - - - Returns an iterator over the bytes in this . - - An iterator over the bytes in this object. - - - - Creates a CodedInputStream from this ByteString's data. - - - - - Compares two byte strings for equality. - - The first byte string to compare. - The second byte string to compare. - true if the byte strings are equal; false otherwise. - - - - Compares two byte strings for inequality. - - The first byte string to compare. - The second byte string to compare. - false if the byte strings are equal; true otherwise. - - - - Compares this byte string with another object. - - The object to compare this with. - true if refers to an equal ; false otherwise. - - - - Returns a hash code for this object. Two equal byte strings - will return the same hash code. - - A hash code for this object. - - - - Compares this byte string with another. - - The to compare this with. - true if refers to an equal byte string; false otherwise. - - - - Copies the entire byte array to the destination array provided at the offset specified. - - - - - Writes the entire byte array to the provided stream - - - - - SecuritySafeCritical attribute can not be placed on types with async methods. - This class has ByteString's async methods so it can be marked with SecuritySafeCritical. - - - - - Reads and decodes protocol message fields. - - - - This class is generally used by generated code to read appropriate - primitives from the stream. It effectively encapsulates the lowest - levels of protocol buffer format. - - - Repeated fields and map fields are not handled by this class; use - and to serialize such fields. - - - - - - Whether to leave the underlying stream open when disposing of this stream. - This is always true when there's no stream. - - - - - Buffer of data read from the stream or provided at construction time. - - - - - The stream to read further input from, or null if the byte array buffer was provided - directly on construction, with no further data available. - - - - - The parser state is kept separately so that other parse implementations can reuse the same - parsing primitives. - - - - - Creates a new CodedInputStream reading data from the given byte array. - - - - - Creates a new that reads from the given byte array slice. - - - - - Creates a new reading data from the given stream, which will be disposed - when the returned object is disposed. - - The stream to read from. - - - - Creates a new reading data from the given stream. - - The stream to read from. - true to leave open when the returned - is disposed; false to dispose of the given stream when the - returned object is disposed. - - - - Creates a new CodedInputStream reading data from the given - stream and buffer, using the default limits. - - - - - Creates a new CodedInputStream reading data from the given - stream and buffer, using the specified limits. - - - This chains to the version with the default limits instead of vice versa to avoid - having to check that the default values are valid every time. - - - - - Creates a with the specified size and recursion limits, reading - from an input stream. - - - This method exists separately from the constructor to reduce the number of constructor overloads. - It is likely to be used considerably less frequently than the constructors, as the default limits - are suitable for most use cases. - - The input stream to read from - The total limit of data to read from the stream. - The maximum recursion depth to allow while reading. - A CodedInputStream reading from with the specified size - and recursion limits. - - - - Returns the current position in the input stream, or the position in the input buffer - - - - - Returns the last tag read, or 0 if no tags have been read or we've read beyond - the end of the stream. - - - - - Returns the size limit for this stream. - - - This limit is applied when reading from the underlying stream, as a sanity check. It is - not applied when reading from a byte array data source without an underlying stream. - The default value is Int32.MaxValue. - - - The size limit. - - - - - Returns the recursion limit for this stream. This limit is applied whilst reading messages, - to avoid maliciously-recursive data. - - - The default limit is 100. - - - The recursion limit for this stream. - - - - - Internal-only property; when set to true, unknown fields will be discarded while parsing. - - - - - Internal-only property; provides extension identifiers to compatible messages while parsing. - - - - - Disposes of this instance, potentially closing any underlying stream. - - - As there is no flushing to perform here, disposing of a which - was constructed with the leaveOpen option parameter set to true (or one which - was constructed to read from a byte array) has no effect. - - - - - Verifies that the last call to ReadTag() returned tag 0 - in other words, - we've reached the end of the stream when we expected to. - - The - tag read was not the one specified - - - - Peeks at the next field tag. This is like calling , but the - tag is not consumed. (So a subsequent call to will return the - same value.) - - - - - Reads a field tag, returning the tag of 0 for "end of stream". - - - If this method returns 0, it doesn't necessarily mean the end of all - the data in this CodedInputStream; it may be the end of the logical stream - for an embedded message, for example. - - The next field tag, or 0 for end of stream. (0 is never a valid tag.) - - - - Skips the data for the field with the tag we've just read. - This should be called directly after , when - the caller wishes to skip an unknown field. - - - This method throws if the last-read tag was an end-group tag. - If a caller wishes to skip a group, they should skip the whole group, by calling this method after reading the - start-group tag. This behavior allows callers to call this method on any field they don't understand, correctly - resulting in an error if an end-group tag has not been paired with an earlier start-group tag. - - The last tag was an end-group tag - The last read operation read to the end of the logical stream - - - - Skip a group. - - - - - Reads a double field from the stream. - - - - - Reads a float field from the stream. - - - - - Reads a uint64 field from the stream. - - - - - Reads an int64 field from the stream. - - - - - Reads an int32 field from the stream. - - - - - Reads a fixed64 field from the stream. - - - - - Reads a fixed32 field from the stream. - - - - - Reads a bool field from the stream. - - - - - Reads a string field from the stream. - - - - - Reads an embedded message field value from the stream. - - - - - Reads an embedded group field from the stream. - - - - - Reads a bytes field value from the stream. - - - - - Reads a uint32 field value from the stream. - - - - - Reads an enum field value from the stream. - - - - - Reads an sfixed32 field value from the stream. - - - - - Reads an sfixed64 field value from the stream. - - - - - Reads an sint32 field value from the stream. - - - - - Reads an sint64 field value from the stream. - - - - - Reads a length for length-delimited data. - - - This is internally just reading a varint, but this method exists - to make the calling code clearer. - - - - - Peeks at the next tag in the stream. If it matches , - the tag is consumed and the method returns true; otherwise, the - stream is left in the original position and the method returns false. - - - - - Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits. - This method is optimised for the case where we've got lots of data in the buffer. - That means we can check the size just once, then just read directly from the buffer - without constant rechecking of the buffer length. - - - - - Reads a varint from the input one byte at a time, so that it does not - read any bytes after the end of the varint. If you simply wrapped the - stream in a CodedInputStream and used ReadRawVarint32(Stream) - then you would probably end up reading past the end of the varint since - CodedInputStream buffers its input. - - - - - - - Reads a raw varint from the stream. - - - - - Reads a 32-bit little-endian integer from the stream. - - - - - Reads a 64-bit little-endian integer from the stream. - - - - - Sets currentLimit to (current position) + byteLimit. This is called - when descending into a length-delimited embedded message. The previous - limit is returned. - - The old limit. - - - - Discards the current limit, returning the previous limit. - - - - - Returns whether or not all the data before the limit has been read. - - - - - - Returns true if the stream has reached the end of the input. This is the - case if either the end of the underlying input source has been reached or - the stream has reached a limit created using PushLimit. - - - - - Called when buffer is empty to read more bytes from the - input. If is true, RefillBuffer() guarantees that - either there will be at least one byte in the buffer when it returns - or it will throw an exception. If is false, - RefillBuffer() returns false if no more bytes were available. - - - - - - - Reads a fixed size of bytes from the input. - - - the end of the stream or the current limit was reached - - - - - Reads a top-level message or a nested message after the limits for this message have been pushed. - (parser will proceed until the end of the current limit) - NOTE: this method needs to be public because it's invoked by the generated code - e.g. msg.MergeFrom(CodedInputStream input) method - - - - - Encodes and writes protocol message fields. - - - - This class is generally used by generated code to write appropriate - primitives to the stream. It effectively encapsulates the lowest - levels of protocol buffer format. Unlike some other implementations, - this does not include combined "write tag and value" methods. Generated - code knows the exact byte representations of the tags they're going to write, - so there's no need to re-encode them each time. Manually-written code calling - this class should just call one of the WriteTag overloads before each value. - - - Repeated fields and map fields are not handled by this class; use RepeatedField<T> - and MapField<TKey, TValue> to serialize such fields. - - - - - - Computes the number of bytes that would be needed to encode a - double field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - float field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - uint64 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode an - int64 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode an - int32 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - fixed64 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - fixed32 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - bool field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - string field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - group field, including the tag. - - - - - Computes the number of bytes that would be needed to encode an - embedded message field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - bytes field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - uint32 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a - enum field, including the tag. The caller is responsible for - converting the enum value to its numeric value. - - - - - Computes the number of bytes that would be needed to encode an - sfixed32 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode an - sfixed64 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode an - sint32 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode an - sint64 field, including the tag. - - - - - Computes the number of bytes that would be needed to encode a length, - as written by . - - - - - Computes the number of bytes that would be needed to encode a varint. - - - - - Computes the number of bytes that would be needed to encode a varint. - - - - - Computes the number of bytes that would be needed to encode a tag. - - - - - The buffer size used by CreateInstance(Stream). - - - - - Creates a new CodedOutputStream that writes directly to the given - byte array. If more bytes are written than fit in the array, - OutOfSpaceException will be thrown. - - - - - Creates a new CodedOutputStream that writes directly to the given - byte array slice. If more bytes are written than fit in the array, - OutOfSpaceException will be thrown. - - - - - Creates a new which write to the given stream, and disposes of that - stream when the returned CodedOutputStream is disposed. - - The stream to write to. It will be disposed when the returned CodedOutputStream is disposed. - - - - Creates a new CodedOutputStream which write to the given stream and uses - the specified buffer size. - - The stream to write to. It will be disposed when the returned CodedOutputStream is disposed. - The size of buffer to use internally. - - - - Creates a new CodedOutputStream which write to the given stream. - - The stream to write to. - If true, is left open when the returned CodedOutputStream is disposed; - if false, the provided stream is disposed as well. - - - - Creates a new CodedOutputStream which write to the given stream and uses - the specified buffer size. - - The stream to write to. - The size of buffer to use internally. - If true, is left open when the returned CodedOutputStream is disposed; - if false, the provided stream is disposed as well. - - - - Returns the current position in the stream, or the position in the output buffer - - - - - Writes a double field value, without a tag, to the stream. - - The value to write - - - - Writes a float field value, without a tag, to the stream. - - The value to write - - - - Writes a uint64 field value, without a tag, to the stream. - - The value to write - - - - Writes an int64 field value, without a tag, to the stream. - - The value to write - - - - Writes an int32 field value, without a tag, to the stream. - - The value to write - - - - Writes a fixed64 field value, without a tag, to the stream. - - The value to write - - - - Writes a fixed32 field value, without a tag, to the stream. - - The value to write - - - - Writes a bool field value, without a tag, to the stream. - - The value to write - - - - Writes a string field value, without a tag, to the stream. - The data is length-prefixed. - - The value to write - - - - Writes a message, without a tag, to the stream. - The data is length-prefixed. - - The value to write - - - - Writes a message, without a tag, to the stream. - Only the message data is written, without a length-delimiter. - - The value to write - - - - Writes a group, without a tag, to the stream. - - The value to write - - - - Write a byte string, without a tag, to the stream. - The data is length-prefixed. - - The value to write - - - - Writes a uint32 value, without a tag, to the stream. - - The value to write - - - - Writes an enum value, without a tag, to the stream. - - The value to write - - - - Writes an sfixed32 value, without a tag, to the stream. - - The value to write. - - - - Writes an sfixed64 value, without a tag, to the stream. - - The value to write - - - - Writes an sint32 value, without a tag, to the stream. - - The value to write - - - - Writes an sint64 value, without a tag, to the stream. - - The value to write - - - - Writes a length (in bytes) for length-delimited data. - - - This method simply writes a rawint, but exists for clarity in calling code. - - Length value, in bytes. - - - - Encodes and writes a tag. - - The number of the field to write the tag for - The wire format type of the tag to write - - - - Writes an already-encoded tag. - - The encoded tag - - - - Writes the given single-byte tag directly to the stream. - - The encoded tag - - - - Writes the given two-byte tag directly to the stream. - - The first byte of the encoded tag - The second byte of the encoded tag - - - - Writes the given three-byte tag directly to the stream. - - The first byte of the encoded tag - The second byte of the encoded tag - The third byte of the encoded tag - - - - Writes the given four-byte tag directly to the stream. - - The first byte of the encoded tag - The second byte of the encoded tag - The third byte of the encoded tag - The fourth byte of the encoded tag - - - - Writes the given five-byte tag directly to the stream. - - The first byte of the encoded tag - The second byte of the encoded tag - The third byte of the encoded tag - The fourth byte of the encoded tag - The fifth byte of the encoded tag - - - - Writes a 32 bit value as a varint. The fast route is taken when - there's enough buffer space left to whizz through without checking - for each byte; otherwise, we resort to calling WriteRawByte each time. - - - - - Writes out an array of bytes. - - - - - Writes out part of an array of bytes. - - - - - Indicates that a CodedOutputStream wrapping a flat byte array - ran out of space. - - - - - Flushes any buffered data and optionally closes the underlying stream, if any. - - - - By default, any underlying stream is closed by this method. To configure this behaviour, - use a constructor overload with a leaveOpen parameter. If this instance does not - have an underlying stream, this method does nothing. - - - For the sake of efficiency, calling this method does not prevent future write calls - but - if a later write ends up writing to a stream which has been disposed, that is likely to - fail. It is recommend that you not call any other methods after this. - - - - - - Flushes any buffered data to the underlying stream (if there is one). - - - - - Verifies that SpaceLeft returns zero. It's common to create a byte array - that is exactly big enough to hold a message, then write to it with - a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that - the message was actually as big as expected, which can help finding bugs. - - - - - If writing to a flat array, returns the space left in the array. Otherwise, - throws an InvalidOperationException. - - - - - Utility to compare if two Lists are the same, and the hash code - of a List. - - - - - Checks if two lists are equal. - - - - - Gets the list's hash code. - - - - - Representation of a map field in a Protocol Buffer message. - - Key type in the map. Must be a type supported by Protocol Buffer map keys. - Value type in the map. Must be a type supported by Protocol Buffers. - - - For string keys, the equality comparison is provided by . - - - Null values are not permitted in the map, either for wrapper types or regular messages. - If a map is deserialized from a data stream and the value is missing from an entry, a default value - is created instead. For primitive types, that is the regular default value (0, the empty string and so - on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length - encoded value for the field. - - - This implementation does not generally prohibit the use of key/value types which are not - supported by Protocol Buffers (e.g. using a key type of byte) but nor does it guarantee - that all operations will work in such cases. - - - The order in which entries are returned when iterating over this object is undefined, and may change - in future versions. - - - - - - Creates a deep clone of this object. - - - A deep clone of this object. - - - - - Adds the specified key/value pair to the map. - - - This operation fails if the key already exists in the map. To replace an existing entry, use the indexer. - - The key to add - The value to add. - The given key already exists in map. - - - - Determines whether the specified key is present in the map. - - The key to check. - true if the map contains the given key; false otherwise. - - - - Removes the entry identified by the given key from the map. - - The key indicating the entry to remove from the map. - true if the map contained the given key before the entry was removed; false otherwise. - - - - Gets the value associated with the specified key. - - The key whose value to get. - When this method returns, the value associated with the specified key, if the key is found; - otherwise, the default value for the type of the parameter. - This parameter is passed uninitialized. - true if the map contains an element with the specified key; otherwise, false. - - - - Gets or sets the value associated with the specified key. - - The key of the value to get or set. - The property is retrieved and key does not exist in the collection. - The value associated with the specified key. If the specified key is not found, - a get operation throws a , and a set operation creates a new element with the specified key. - - - - Gets a collection containing the keys in the map. - - - - - Gets a collection containing the values in the map. - - - - - Adds the specified entries to the map. The keys and values are not automatically cloned. - - The entries to add to the map. - - - - Returns an enumerator that iterates through the collection. - - - An enumerator that can be used to iterate through the collection. - - - - - Returns an enumerator that iterates through a collection. - - - An object that can be used to iterate through the collection. - - - - - Adds the specified item to the map. - - The item to add to the map. - - - - Removes all items from the map. - - - - - Determines whether map contains an entry equivalent to the given key/value pair. - - The key/value pair to find. - - - - - Copies the key/value pairs in this map to an array. - - The array to copy the entries into. - The index of the array at which to start copying values. - - - - Removes the specified key/value pair from the map. - - Both the key and the value must be found for the entry to be removed. - The key/value pair to remove. - true if the key/value pair was found and removed; false otherwise. - - - - Gets the number of elements contained in the map. - - - - - Gets a value indicating whether the map is read-only. - - - - - Determines whether the specified , is equal to this instance. - - The to compare with this instance. - - true if the specified is equal to this instance; otherwise, false. - - - - - Returns a hash code for this instance. - - - A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - - - - - Compares this map with another for equality. - - - The order of the key/value pairs in the maps is not deemed significant in this comparison. - - The map to compare this with. - true if refers to an equal map; false otherwise. - - - - Adds entries to the map from the given stream. - - - It is assumed that the stream is initially positioned after the tag specified by the codec. - This method will continue reading entries from the stream until the end is reached, or - a different tag is encountered. - - Stream to read from - Codec describing how the key/value pairs are encoded - - - - Adds entries to the map from the given parse context. - - - It is assumed that the input is initially positioned after the tag specified by the codec. - This method will continue reading entries from the input until the end is reached, or - a different tag is encountered. - - Input to read from - Codec describing how the key/value pairs are encoded - - - - Writes the contents of this map to the given coded output stream, using the specified codec - to encode each entry. - - The output stream to write to. - The codec to use for each entry. - - - - Writes the contents of this map to the given write context, using the specified codec - to encode each entry. - - The write context to write to. - The codec to use for each entry. - - - - Calculates the size of this map based on the given entry codec. - - The codec to use to encode each entry. - - - - - Returns a string representation of this repeated field, in the same - way as it would be represented by the default JSON formatter. - - - - - A codec for a specific map field. This contains all the information required to encode and - decode the nested messages. - - - - - Creates a new entry codec based on a separate key codec and value codec, - and the tag to use for each map entry. - - The key codec. - The value codec. - The map tag to use to introduce each map entry. - - - - The key codec. - - - - - The value codec. - - - - - The tag used in the enclosing message to indicate map entries. - - - - - Provides a central place to implement equality comparisons, primarily for bitwise float/double equality. - - - - - Returns an equality comparer for suitable for Protobuf equality comparisons. - This is usually just the default equality comparer for the type, but floating point numbers are compared - bitwise. - - The type of equality comparer to return. - The equality comparer. - - - - Returns an equality comparer suitable for comparing 64-bit floating point values, by bitwise comparison. - (NaN values are considered equal, but only when they have the same representation.) - - - - - Returns an equality comparer suitable for comparing 32-bit floating point values, by bitwise comparison. - (NaN values are considered equal, but only when they have the same representation.) - - - - - Returns an equality comparer suitable for comparing nullable 64-bit floating point values, by bitwise comparison. - (NaN values are considered equal, but only when they have the same representation.) - - - - - Returns an equality comparer suitable for comparing nullable 32-bit floating point values, by bitwise comparison. - (NaN values are considered equal, but only when they have the same representation.) - - - - - Read-only wrapper around another dictionary. - - - - - The contents of a repeated field: essentially, a collection with some extra - restrictions (no null values) and capabilities (deep cloning). - - - This implementation does not generally prohibit the use of types which are not - supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases. - - The element type of the repeated field. - - - - Creates a deep clone of this repeated field. - - - If the field type is - a message type, each element is also cloned; otherwise, it is - assumed that the field type is primitive (including string and - bytes, both of which are immutable) and so a simple copy is - equivalent to a deep clone. - - A deep clone of this repeated field. - - - - Adds the entries from the given input stream, decoding them with the specified codec. - - The input stream to read from. - The codec to use in order to read each entry. - - - - Adds the entries from the given parse context, decoding them with the specified codec. - - The input to read from. - The codec to use in order to read each entry. - - - - Calculates the size of this collection based on the given codec. - - The codec to use when encoding each field. - The number of bytes that would be written to an output by one of the WriteTo methods, - using the same codec. - - - - Writes the contents of this collection to the given , - encoding each value using the specified codec. - - The output stream to write to. - The codec to use when encoding each value. - - - - Writes the contents of this collection to the given write context, - encoding each value using the specified codec. - - The write context to write to. - The codec to use when encoding each value. - - - - Gets and sets the capacity of the RepeatedField's internal array. WHen set, the internal array is reallocated to the given capacity. - The new value is less than Count -or- when Count is less than 0. - - - - - Adds the specified item to the collection. - - The item to add. - - - - Removes all items from the collection. - - - - - Determines whether this collection contains the given item. - - The item to find. - true if this collection contains the given item; false otherwise. - - - - Copies this collection to the given array. - - The array to copy to. - The first index of the array to copy to. - - - - Removes the specified item from the collection - - The item to remove. - true if the item was found and removed; false otherwise. - - - - Gets the number of elements contained in the collection. - - - - - Gets a value indicating whether the collection is read-only. - - - - - Adds all of the specified values into this collection. - - The values to add to this collection. - - - - Adds all of the specified values into this collection. This method is present to - allow repeated fields to be constructed from queries within collection initializers. - Within non-collection-initializer code, consider using the equivalent - method instead for clarity. - - The values to add to this collection. - - - - Returns an enumerator that iterates through the collection. - - - An enumerator that can be used to iterate through the collection. - - - - - Determines whether the specified , is equal to this instance. - - The to compare with this instance. - - true if the specified is equal to this instance; otherwise, false. - - - - - Returns an enumerator that iterates through a collection. - - - An object that can be used to iterate through the collection. - - - - - Returns a hash code for this instance. - - - A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - - - - - Compares this repeated field with another for equality. - - The repeated field to compare this with. - true if refers to an equal repeated field; false otherwise. - - - - Returns the index of the given item within the collection, or -1 if the item is not - present. - - The item to find in the collection. - The zero-based index of the item, or -1 if it is not found. - - - - Inserts the given item at the specified index. - - The index at which to insert the item. - The item to insert. - - - - Removes the item at the given index. - - The zero-based index of the item to remove. - - - - Returns a string representation of this repeated field, in the same - way as it would be represented by the default JSON formatter. - - - - - Gets or sets the item at the specified index. - - - The element at the specified index. - - The zero-based index of the element to get or set. - The item at the specified index. - - - - Extension methods for , effectively providing - the familiar members from previous desktop framework versions while - targeting the newer releases, .NET Core etc. - - - - - Returns the public getter of a property, or null if there is no such getter - (either because it's read-only, or the getter isn't public). - - - - - Returns the public setter of a property, or null if there is no such setter - (either because it's write-only, or the setter isn't public). - - - - - Provides extension methods on Type that just proxy to TypeInfo. - These are used to support the new type system from .NET 4.5, without - having calls to GetTypeInfo all over the place. While the methods here are meant to be - broadly compatible with the desktop framework, there are some subtle differences in behaviour - but - they're not expected to affect our use cases. While the class is internal, that should be fine: we can - evaluate each new use appropriately. - - - - - See https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom - - - - - Returns a representation of the public property associated with the given name in the given type, - including inherited properties or null if there is no such public property. - Here, "public property" means a property where either the getter, or the setter, or both, is public. - - - - - Returns a representation of the public method associated with the given name in the given type, - including inherited methods. - - - This has a few differences compared with Type.GetMethod in the desktop framework. It will throw - if there is an ambiguous match even between a private method and a public one, but it *won't* throw - if there are two overloads at different levels in the type hierarchy (e.g. class Base declares public void Foo(int) and - class Child : Base declares public void Foo(long)). - - One type in the hierarchy declared more than one method with the same name - - - - Represents a non-generic extension definition. This API is experimental and subject to change. - - - - - Internal use. Creates a new extension with the specified field number. - - - - - Gets the field number of this extension - - - - - Represents a type-safe extension identifier used for getting and setting single extension values in instances. - This API is experimental and subject to change. - - The message type this field applies to - The field value type of this extension - - - - Creates a new extension identifier with the specified field number and codec - - - - - Represents a type-safe extension identifier used for getting repeated extension values in instances. - This API is experimental and subject to change. - - The message type this field applies to - The repeated field value type of this extension - - - - Creates a new repeated extension identifier with the specified field number and codec - - - - - Provides extensions to messages while parsing. This API is experimental and subject to change. - - - - - Creates a new empty extension registry - - - - - Gets the total number of extensions in this extension registry - - - - - Returns whether the registry is readonly - - - - - Adds the specified extension to the registry - - - - - Adds the specified extensions to the registry - - - - - Clears the registry of all values - - - - - Gets whether the extension registry contains the specified extension - - - - - Copies the arrays in the registry set to the specified array at the specified index - - The array to copy to - The array index to start at - - - - Returns an enumerator to enumerate through the items in the registry - - Returns an enumerator for the extensions in this registry - - - - Removes the specified extension from the set - - The extension - true if the extension was removed, otherwise false - - - - Clones the registry into a new registry - - - - - Methods for managing s with null checking. - - Most users will not use this class directly and its API is experimental and subject to change. - - - - - Gets the value of the specified extension - - - - - Gets the value of the specified repeated extension or null if it doesn't exist in this set - - - - - Gets the value of the specified repeated extension, registering it if it doesn't exist - - - - - Sets the value of the specified extension. This will make a new instance of ExtensionSet if the set is null. - - - - - Gets whether the value of the specified extension is set - - - - - Clears the value of the specified extension - - - - - Clears the value of the specified extension - - - - - Tries to merge a field from the coded input, returning true if the field was merged. - If the set is null or the field was not otherwise merged, this returns false. - - - - - Tries to merge a field from the coded input, returning true if the field was merged. - If the set is null or the field was not otherwise merged, this returns false. - - - - - Merges the second set into the first set, creating a new instance if first is null - - - - - Clones the set into a new set. If the set is null, this returns null - - - - - Used for keeping track of extensions in messages. - methods route to this set. - - Most users will not need to use this class directly - - The message type that extensions in this set target - - - - Gets a hash code of the set - - - - - Returns whether this set is equal to the other object - - - - - Calculates the size of this extension set - - - - - Writes the extension values in this set to the output stream - - - - - Writes the extension values in this set to the write context - - - - - Factory methods for . - - - - - Retrieves a codec suitable for a string field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for a bytes field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for a bool field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for an int32 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for an sint32 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for a fixed32 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for an sfixed32 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for a uint32 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for an int64 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for an sint64 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for a fixed64 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for an sfixed64 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for a uint64 field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for a float field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for a double field with the given tag. - - The tag. - A codec for the given tag. - - - - Retrieves a codec suitable for an enum field with the given tag. - - The tag. - A conversion function from to the enum type. - A conversion function from the enum type to . - A codec for the given tag. - - - - Retrieves a codec suitable for a string field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a bytes field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a bool field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for an int32 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for an sint32 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a fixed32 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for an sfixed32 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a uint32 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for an int64 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for an sint64 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a fixed64 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for an sfixed64 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a uint64 field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a float field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a double field with the given tag. - - The tag. - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for an enum field with the given tag. - - The tag. - A conversion function from to the enum type. - A conversion function from the enum type to . - The default value. - A codec for the given tag. - - - - Retrieves a codec suitable for a message field with the given tag. - - The tag. - A parser to use for the message type. - A codec for the given tag. - - - - Retrieves a codec suitable for a group field with the given tag. - - The start group tag. - The end group tag. - A parser to use for the group message type. - A codec for given tag - - - - Creates a codec for a wrapper type of a class - which must be string or ByteString. - - - - - Creates a codec for a wrapper type of a struct - which must be Int32, Int64, UInt32, UInt64, - Bool, Single or Double. - - - - - Helper code to create codecs for wrapper types. - - - Somewhat ugly with all the static methods, but the conversions involved to/from nullable types make it - slightly tricky to improve. So long as we keep the public API (ForClassWrapper, ForStructWrapper) in place, - we can refactor later if we come up with something cleaner. - - - - - Returns a field codec which effectively wraps a value of type T in a message. - - - - - - - An encode/decode pair for a single field. This effectively encapsulates - all the information needed to read or write the field value from/to a coded - stream. - - - This class is public and has to be as it is used by generated code, but its public - API is very limited - just what the generated code needs to call directly. - - - - This never writes default values to the stream, and does not address "packedness" - in repeated fields itself, other than to know whether or not the field *should* be packed. - - - - - Merges an input stream into a value - - - - - Merges a value into a reference to another value, returning a boolean if the value was set - - - - - Returns a delegate to write a value (unconditionally) to a coded output stream. - - - - - Returns the size calculator for just a value. - - - - - Returns a delegate to read a value from a coded input stream. It is assumed that - the stream is already positioned on the appropriate tag. - - - - - Returns a delegate to merge a value from a coded input stream. - It is assumed that the stream is already positioned on the appropriate tag - - - - - Returns a delegate to merge two values together. - - - - - Returns the fixed size for an entry, or 0 if sizes vary. - - - - - Gets the tag of the codec. - - - The tag of the codec. - - - - - Gets the end tag of the codec or 0 if there is no end tag - - - The end tag of the codec. - - - - - Default value for this codec. Usually the same for every instance of the same type, but - for string/ByteString wrapper fields the codec's default value is null, whereas for - other string/ByteString fields it's "" or ByteString.Empty. - - - The default value of the codec's type. - - - - - Write a tag and the given value, *if* the value is not the default. - - - - - Write a tag and the given value, *if* the value is not the default. - - - - - Reads a value of the codec type from the given . - - The input stream to read from. - The value read from the stream. - - - - Reads a value of the codec type from the given . - - The parse context to read from. - The value read. - - - - Calculates the size required to write the given value, with a tag, - if the value is not the default. - - - - - Calculates the size required to write the given value, with a tag, even - if the value is the default. - - - - - A tree representation of a FieldMask. Each leaf node in this tree represent - a field path in the FieldMask. - - For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be: - - [root] -+- foo -+- bar - | | - | +- baz - | - +- bar --- baz - - - By representing FieldMasks with this tree structure we can easily convert - a FieldMask to a canonical form, merge two FieldMasks, calculate the - intersection to two FieldMasks and traverse all fields specified by the - FieldMask in a message tree. - - - - - Creates an empty FieldMaskTree. - - - - - Creates a FieldMaskTree for a given FieldMask. - - - - - Adds a field path to the tree. In a FieldMask, every field path matches the - specified field as well as all its sub-fields. For example, a field path - "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding - a field path to the tree, redundant sub-paths will be removed. That is, - after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it - exists, which will turn the tree node for "foo.bar" to a leaf node. - Likewise, if the field path to add is a sub-path of an existing leaf node, - nothing will be changed in the tree. - - - - - Merges all field paths in a FieldMask into this tree. - - - - - Converts this tree to a FieldMask. - - - - - Gathers all field paths in a sub-tree. - - - - - Adds the intersection of this tree with the given to . - - - - - Merges all fields specified by this FieldMaskTree from to . - - - - - Merges all fields specified by a sub-tree from to . - - - - - Class containing helpful workarounds for various platform compatibility - - - - - Interface for a Protocol Buffers message, supporting - parsing from and writing to . - - - - - Internal implementation of merging data from given parse context into this message. - Users should never invoke this method directly. - - - - - Internal implementation of writing this message to a given write context. - Users should never invoke this method directly. - - - - - A message type that has a custom string format for diagnostic purposes. - - - - Calling on a generated message type normally - returns the JSON representation. If a message type implements this interface, - then the method will be called instead of the regular - JSON formatting code, but only when ToString() is called either on the message itself - or on another message which contains it. This does not affect the normal JSON formatting of - the message. - - - For example, if you create a proto message representing a GUID, the internal - representation may be a bytes field or four fixed32 fields. However, when debugging - it may be more convenient to see a result in the same format as provides. - - This interface extends to avoid it accidentally being implemented - on types other than messages, where it would not be used by anything in the framework. - - - - - Returns a string representation of this object, for diagnostic purposes. - - - This method is called when a message is formatted as part of a - call. It does not affect the JSON representation used by other than - in calls to . While it is recommended - that the result is valid JSON, this is never assumed by the Protobuf library. - - A string representation of this object, for diagnostic purposes. - - - - Generic interface for a deeply cloneable type. - - - - All generated messages implement this interface, but so do some non-message types. - Additionally, due to the type constraint on T in , - it is simpler to keep this as a separate interface. - - - The type itself, returned by the method. - - - - Creates a deep clone of this object. - - A deep clone of this object. - - - - Generic interface for a Protocol Buffers message containing one or more extensions, where the type parameter is expected to be the same type as the implementation class. - This interface is experiemental and is subject to change. - - - - - Gets the value of the specified extension - - - - - Gets the value of the specified repeated extension or null if the extension isn't registered in this set. - For a version of this method that never returns null, use - - - - - Gets the value of the specified repeated extension, registering it if it hasn't already been registered. - - - - - Sets the value of the specified extension - - - - - Gets whether the value of the specified extension is set - - - - - Clears the value of the specified extension - - - - - Clears the value of the specified repeated extension - - - - - Interface for a Protocol Buffers message, supporting - basic operations required for serialization. - - - - - Merges the data from the specified coded input stream with the current message. - - See the user guide for precise merge semantics. - - - - - Writes the data to the given coded output stream. - - Coded output stream to write the data to. Must not be null. - - - - Calculates the size of this message in Protocol Buffer wire format, in bytes. - - The number of bytes required to write this message - to a coded output stream. - - - - Descriptor for this message. All instances are expected to return the same descriptor, - and for generated types this will be an explicitly-implemented member, returning the - same value as the static property declared on the type. - - - - - Generic interface for a Protocol Buffers message, - where the type parameter is expected to be the same type as - the implementation class. - - The message type. - - - - Merges the given message into this one. - - See the user guide for precise merge semantics. - The message to merge with this one. Must not be null. - - - - Thrown when an attempt is made to parse invalid JSON, e.g. using - a non-string property key, or including a redundant comma. Parsing a protocol buffer - message represented in JSON using can throw both this - exception and depending on the situation. This - exception is only thrown for "pure JSON" errors, whereas InvalidProtocolBufferException - is thrown when the JSON may be valid in and of itself, but cannot be parsed as a protocol buffer - message. - - - - - Thrown when a protocol message being parsed is invalid in some way, - e.g. it contains a malformed varint or a negative byte length. - - - - - Creates an exception for an error condition of an invalid tag being encountered. - - - - - Reflection-based converter from messages to JSON. - - - - Instances of this class are thread-safe, with no mutable state. - - - This is a simple start to get JSON formatting working. As it's reflection-based, - it's not as quick as baking calls into generated messages - but is a simpler implementation. - (This code is generally not heavily optimized.) - - - - - - Returns a formatter using the default settings. - - - - - The JSON representation of the first 160 characters of Unicode. - Empty strings are replaced by the static constructor. - - - - - Creates a new formatted with the given settings. - - The settings. - - - - Formats the specified message as JSON. - - The message to format. - The formatted message. - - - - Formats the specified message as JSON. - - The message to format. - The TextWriter to write the formatted message to. - The formatted message. - - - - Converts a message to JSON for diagnostic purposes with no extra context. - - - - This differs from calling on the default JSON - formatter in its handling of . As no type registry is available - in calls, the normal way of resolving the type of - an Any message cannot be applied. Instead, a JSON property named @value - is included with the base64 data from the property of the message. - - The value returned by this method is only designed to be used for diagnostic - purposes. It may not be parsable by , and may not be parsable - by other Protocol Buffer implementations. - - The message to format for diagnostic purposes. - The diagnostic-only JSON representation of the message - - - - Determines whether or not a field value should be serialized according to the field, - its value in the message, and the settings of this formatter. - - - - - Writes a single value to the given writer as JSON. Only types understood by - Protocol Buffers can be written in this way. This method is only exposed for - advanced use cases; most users should be using - or . - - The writer to write the value to. Must not be null. - The value to write. May be null. - - - - Central interception point for well-known type formatting. Any well-known types which - don't need special handling can fall back to WriteMessage. We avoid assuming that the - values are using the embedded well-known types, in order to allow for dynamic messages - in the future. - - - - - Writes a string (including leading and trailing double quotes) to a builder, escaping as required. - - - Other than surrogate pair handling, this code is mostly taken from src/google/protobuf/util/internal/json_escaping.cc. - - - - - Settings controlling JSON formatting. - - - - - Default settings, as used by - - - - - Whether fields which would otherwise not be included in the formatted data - should be formatted even when the value is not present, or has the default value. - This option only affects fields which don't support "presence" (e.g. - singular non-optional proto3 primitive fields). - - - - - The type registry used to format messages. - - - - - Whether to format enums as ints. Defaults to false. - - - - - Whether to use the original proto field names as defined in the .proto file. Defaults to false. - - - - - Creates a new object with the specified formatting of default values - and an empty type registry. - - true if default values (0, empty strings etc) should be formatted; false otherwise. - - - - Creates a new object with the specified formatting of default values - and type registry. - - true if default values (0, empty strings etc) should be formatted; false otherwise. - The to use when formatting messages. - - - - Creates a new object with the specified parameters. - - true if default values (0, empty strings etc) should be formatted; false otherwise. - The to use when formatting messages. TypeRegistry.Empty will be used if it is null. - true to format the enums as integers; false to format enums as enum names. - true to preserve proto field names; false to convert them to lowerCamelCase. - - - - Creates a new object with the specified formatting of default values and the current settings. - - true if default values (0, empty strings etc) should be formatted; false otherwise. - - - - Creates a new object with the specified type registry and the current settings. - - The to use when formatting messages. - - - - Creates a new object with the specified enums formatting option and the current settings. - - true to format the enums as integers; false to format enums as enum names. - - - - Creates a new object with the specified field name formatting option and the current settings. - - true to preserve proto field names; false to convert them to lowerCamelCase. - - - - Reflection-based converter from JSON to messages. - - - - Instances of this class are thread-safe, with no mutable state. - - - This is a simple start to get JSON parsing working. As it's reflection-based, - it's not as quick as baking calls into generated messages - but is a simpler implementation. - (This code is generally not heavily optimized.) - - - - - - Returns a formatter using the default settings. - - - - - Creates a new formatted with the given settings. - - The settings. - - - - Parses and merges the information into the given message. - - The message to merge the JSON information into. - The JSON to parse. - - - - Parses JSON read from and merges the information into the given message. - - The message to merge the JSON information into. - Reader providing the JSON to parse. - - - - Merges the given message using data from the given tokenizer. In most cases, the next - token should be a "start object" token, but wrapper types and nullity can invalidate - that assumption. This is implemented as an LL(1) recursive descent parser over the stream - of tokens provided by the tokenizer. This token stream is assumed to be valid JSON, with the - tokenizer performing that validation - but not every token stream is valid "protobuf JSON". - - - - - Parses into a new message. - - The type of message to create. - The JSON to parse. - The JSON does not comply with RFC 7159 - The JSON does not represent a Protocol Buffers message correctly - - - - Parses JSON read from into a new message. - - The type of message to create. - Reader providing the JSON to parse. - The JSON does not comply with RFC 7159 - The JSON does not represent a Protocol Buffers message correctly - - - - Parses into a new message. - - The JSON to parse. - Descriptor of message type to parse. - The JSON does not comply with RFC 7159 - The JSON does not represent a Protocol Buffers message correctly - - - - Parses JSON read from into a new message. - - Reader providing the JSON to parse. - Descriptor of message type to parse. - The JSON does not comply with RFC 7159 - The JSON does not represent a Protocol Buffers message correctly - - - - Creates a new instance of the message type for the given field. - - - - - Checks that any infinite/NaN values originated from the correct text. - This corrects the lenient whitespace handling of double.Parse/float.Parse, as well as the - way that Mono parses out-of-range values as infinity. - - - - - Settings controlling JSON parsing. - - - - - Default settings, as used by . This has the same default - recursion limit as , and an empty type registry. - - - - - The maximum depth of messages to parse. Note that this limit only applies to parsing - messages, not collections - so a message within a collection within a message only counts as - depth 2, not 3. - - - - - The type registry used to parse messages. - - - - - Whether the parser should ignore unknown fields (true) or throw an exception when - they are encountered (false). - - - - - Creates a new object with the specified recursion limit. - - The maximum depth of messages to parse - - - - Creates a new object with the specified recursion limit and type registry. - - The maximum depth of messages to parse - The type registry used to parse messages - - - - Creates a new object set to either ignore unknown fields, or throw an exception - when unknown fields are encountered. - - true if unknown fields should be ignored when parsing; false to throw an exception. - - - - Creates a new object based on this one, but with the specified recursion limit. - - The new recursion limit. - - - - Creates a new object based on this one, but with the specified type registry. - - The new type registry. Must not be null. - - - - Simple but strict JSON tokenizer, rigidly following RFC 7159. - - - - This tokenizer is stateful, and only returns "useful" tokens - names, values etc. - It does not create tokens for the separator between names and values, or for the comma - between values. It validates the token stream as it goes - so callers can assume that the - tokens it produces are appropriate. For example, it would never produce "start object, end array." - - Implementation details: the base class handles single token push-back and - Not thread-safe. - - - - - Creates a tokenizer that reads from the given text reader. - - - - - Creates a tokenizer that first replays the given list of tokens, then continues reading - from another tokenizer. Note that if the returned tokenizer is "pushed back", that does not push back - on the continuation tokenizer, or vice versa. Care should be taken when using this method - it was - created for the sake of Any parsing. - - - - - Returns the depth of the stack, purely in objects (not collections). - Informally, this is the number of remaining unclosed '{' characters we have. - - - - - Returns the next JSON token in the stream. An EndDocument token is returned to indicate the end of the stream, - after which point Next() should not be called again. - - This implementation provides single-token buffering, and calls if there is no buffered token. - The next token in the stream. This is never null. - This method is called after an EndDocument token has been returned - The input text does not comply with RFC 7159 - - - - Returns the next JSON token in the stream, when requested by the base class. (The method delegates - to this if it doesn't have a buffered token.) - - This method is called after an EndDocument token has been returned - The input text does not comply with RFC 7159 - - - - Skips the value we're about to read. This must only be called immediately after reading a property name. - If the value is an object or an array, the complete object/array is skipped. - - - - - Tokenizer which first exhausts a list of tokens, then consults another tokenizer. - - - - - Tokenizer which does all the *real* work of parsing JSON. - - - - - This method essentially just loops through characters skipping whitespace, validating and - changing state (e.g. from ObjectBeforeColon to ObjectAfterColon) - until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point - it returns the token. Although the method is large, it would be relatively hard to break down further... most - of it is the large switch statement, which sometimes returns and sometimes doesn't. - - - - - Reads a string token. It is assumed that the opening " has already been read. - - - - - Reads an escaped character. It is assumed that the leading backslash has already been read. - - - - - Reads an escaped Unicode 4-nybble hex sequence. It is assumed that the leading \u has already been read. - - - - - Consumes a text-only literal, throwing an exception if the read text doesn't match it. - It is assumed that the first letter of the literal has already been read. - - - - - Validates that we're in a valid state to read a value (using the given error prefix if necessary) - and changes the state to the appropriate one, e.g. ObjectAfterColon to ObjectAfterProperty. - - - - - Pops the top-most container, and sets the state to the appropriate one for the end of a value - in the parent container. - - - - - Possible states of the tokenizer. - - - This is a flags enum purely so we can simply and efficiently represent a set of valid states - for checking. - - Each is documented with an example, - where ^ represents the current position within the text stream. The examples all use string values, - but could be any value, including nested objects/arrays. - The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects). - Any additional notional state of "AfterValue" indicates that a value has been completed, at which - point there's an immediate transition to ExpectedEndOfDocument, ObjectAfterProperty or ArrayAfterValue. - - - These states were derived manually by reading RFC 7159 carefully. - - - - - - ^ { "foo": "bar" } - Before the value in a document. Next states: ObjectStart, ArrayStart, "AfterValue" - - - - - { "foo": "bar" } ^ - After the value in a document. Next states: ReaderExhausted - - - - - { "foo": "bar" } ^ (and already read to the end of the reader) - Terminal state. - - - - - { ^ "foo": "bar" } - Before the *first* property in an object. - Next states: - "AfterValue" (empty object) - ObjectBeforeColon (read a name) - - - - - { "foo" ^ : "bar", "x": "y" } - Next state: ObjectAfterColon - - - - - { "foo" : ^ "bar", "x": "y" } - Before any property other than the first in an object. - (Equivalently: after any property in an object) - Next states: - "AfterValue" (value is simple) - ObjectStart (value is object) - ArrayStart (value is array) - - - - - { "foo" : "bar" ^ , "x" : "y" } - At the end of a property, so expecting either a comma or end-of-object - Next states: ObjectAfterComma or "AfterValue" - - - - - { "foo":"bar", ^ "x":"y" } - Read the comma after the previous property, so expecting another property. - This is like ObjectStart, but closing brace isn't valid here - Next state: ObjectBeforeColon. - - - - - [ ^ "foo", "bar" ] - Before the *first* value in an array. - Next states: - "AfterValue" (read a value) - "AfterValue" (end of array; will pop stack) - - - - - [ "foo" ^ , "bar" ] - After any value in an array, so expecting either a comma or end-of-array - Next states: ArrayAfterComma or "AfterValue" - - - - - [ "foo", ^ "bar" ] - After a comma in an array, so there *must* be another value (simple or complex). - Next states: "AfterValue" (simple value), StartObject, StartArray - - - - - Wrapper around a text reader allowing small amounts of buffering and location handling. - - - - - The buffered next character, if we have one. - - - - - Returns the next character in the stream, or null if we have reached the end. - - - - - - Creates a new exception appropriate for the current state of the reader. - - - - - Stream implementation which proxies another stream, only allowing a certain amount - of data to be read. Note that this is only used to read delimited streams, so it - doesn't attempt to implement everything. - - - - - Extension methods on and . - - - - - Merges data from the given byte array into an existing message. - - The message to merge the data into. - The data to merge, which must be protobuf-encoded binary data. - - - - Merges data from the given byte array slice into an existing message. - - The message to merge the data into. - The data containing the slice to merge, which must be protobuf-encoded binary data. - The offset of the slice to merge. - The length of the slice to merge. - - - - Merges data from the given byte string into an existing message. - - The message to merge the data into. - The data to merge, which must be protobuf-encoded binary data. - - - - Merges data from the given stream into an existing message. - - The message to merge the data into. - Stream containing the data to merge, which must be protobuf-encoded binary data. - - - - Merges data from the given span into an existing message. - - The message to merge the data into. - Span containing the data to merge, which must be protobuf-encoded binary data. - - - - Merges length-delimited data from the given stream into an existing message. - - - The stream is expected to contain a length and then the data. Only the amount of data - specified by the length will be consumed. - - The message to merge the data into. - Stream containing the data to merge, which must be protobuf-encoded binary data. - - - - Converts the given message into a byte array in protobuf encoding. - - The message to convert. - The message data as a byte array. - - - - Writes the given message data to the given stream in protobuf encoding. - - The message to write to the stream. - The stream to write to. - - - - Writes the length and then data of the given message to a stream. - - The message to write. - The output stream to write to. - - - - Converts the given message into a byte string in protobuf encoding. - - The message to convert. - The message data as a byte string. - - - - Writes the given message data to the given buffer writer in protobuf encoding. - - The message to write to the stream. - The stream to write to. - - - - Writes the given message data to the given span in protobuf encoding. - The size of the destination span needs to fit the serialized size - of the message exactly, otherwise an exception is thrown. - - The message to write to the stream. - The span to write to. Size must match size of the message exactly. - - - - Checks if all required fields in a message have values set. For proto3 messages, this returns true - - - - - A general message parser, typically used by reflection-based code as all the methods - return simple . - - - - - Creates a template instance ready for population. - - An empty message. - - - - Parses a message from a byte array. - - The byte array containing the message. Must not be null. - The newly parsed message. - - - - Parses a message from a byte array slice. - - The byte array containing the message. Must not be null. - The offset of the slice to parse. - The length of the slice to parse. - The newly parsed message. - - - - Parses a message from the given byte string. - - The data to parse. - The parsed message. - - - - Parses a message from the given stream. - - The stream to parse. - The parsed message. - - - - Parses a message from the given sequence. - - The data to parse. - The parsed message. - - - - Parses a message from the given span. - - The data to parse. - The parsed message. - - - - Parses a length-delimited message from the given stream. - - - The stream is expected to contain a length and then the data. Only the amount of data - specified by the length will be consumed. - - The stream to parse. - The parsed message. - - - - Parses a message from the given coded input stream. - - The stream to parse. - The parsed message. - - - - Parses a message from the given JSON. - - The JSON to parse. - The parsed message. - The JSON does not comply with RFC 7159 - The JSON does not represent a Protocol Buffers message correctly - - - - Creates a new message parser which optionally discards unknown fields when parsing. - - Whether or not to discard unknown fields when parsing. - A newly configured message parser. - - - - Creates a new message parser which registers extensions from the specified registry upon creating the message instance - - The extensions to register - A newly configured message parser. - - - - A parser for a specific message type. - - -

    - This delegates most behavior to the - implementation within the original type, but - provides convenient overloads to parse from a variety of sources. -

    -

    - Most applications will never need to create their own instances of this type; - instead, use the static Parser property of a generated message type to obtain a - parser for that type. -

    -
    - The type of message to be parsed. -
    - - - Creates a new parser. - - - The factory method is effectively an optimization over using a generic constraint - to require a parameterless constructor: delegates are significantly faster to execute. - - Function to invoke when a new, empty message is required. - - - - Creates a template instance ready for population. - - An empty message. - - - - Parses a message from a byte array. - - The byte array containing the message. Must not be null. - The newly parsed message. - - - - Parses a message from a byte array slice. - - The byte array containing the message. Must not be null. - The offset of the slice to parse. - The length of the slice to parse. - The newly parsed message. - - - - Parses a message from the given byte string. - - The data to parse. - The parsed message. - - - - Parses a message from the given stream. - - The stream to parse. - The parsed message. - - - - Parses a message from the given sequence. - - The data to parse. - The parsed message. - - - - Parses a message from the given span. - - The data to parse. - The parsed message. - - - - Parses a length-delimited message from the given stream. - - - The stream is expected to contain a length and then the data. Only the amount of data - specified by the length will be consumed. - - The stream to parse. - The parsed message. - - - - Parses a message from the given coded input stream. - - The stream to parse. - The parsed message. - - - - Parses a message from the given JSON. - - The JSON to parse. - The parsed message. - The JSON does not comply with RFC 7159 - The JSON does not represent a Protocol Buffers message correctly - - - - Creates a new message parser which optionally discards unknown fields when parsing. - - Whether or not to discard unknown fields when parsing. - A newly configured message parser. - - - - Creates a new message parser which registers extensions from the specified registry upon creating the message instance - - The extensions to register - A newly configured message parser. - - - - Struct used to hold the keys for the fieldByNumber table in DescriptorPool and the keys for the - extensionByNumber table in ExtensionRegistry. - - - - - An opaque struct that represents the current parsing state and is passed along - as the parsing proceeds. - All the public methods are intended to be invoked only by the generated code, - users should never invoke them directly. - - - - - Initialize a , building all from defaults and - the given . - - - - - Initialize a using existing , e.g. from . - - - - - Creates a ParseContext instance from CodedInputStream. - WARNING: internally this copies the CodedInputStream's state, so after done with the ParseContext, - the CodedInputStream's state needs to be updated. - - - - - Returns the last tag read, or 0 if no tags have been read or we've read beyond - the end of the input. - - - - - Internal-only property; when set to true, unknown fields will be discarded while parsing. - - - - - Internal-only property; provides extension identifiers to compatible messages while parsing. - - - - - Reads a field tag, returning the tag of 0 for "end of input". - - - If this method returns 0, it doesn't necessarily mean the end of all - the data in this CodedInputReader; it may be the end of the logical input - for an embedded message, for example. - - The next field tag, or 0 for end of input. (0 is never a valid tag.) - - - - Reads a double field from the input. - - - - - Reads a float field from the input. - - - - - Reads a uint64 field from the input. - - - - - Reads an int64 field from the input. - - - - - Reads an int32 field from the input. - - - - - Reads a fixed64 field from the input. - - - - - Reads a fixed32 field from the input. - - - - - Reads a bool field from the input. - - - - - Reads a string field from the input. - - - - - Reads an embedded message field value from the input. - - - - - Reads an embedded group field from the input. - - - - - Reads a bytes field value from the input. - - - - - Reads a uint32 field value from the input. - - - - - Reads an enum field value from the input. - - - - - Reads an sfixed32 field value from the input. - - - - - Reads an sfixed64 field value from the input. - - - - - Reads an sint32 field value from the input. - - - - - Reads an sint64 field value from the input. - - - - - Reads a length for length-delimited data. - - - This is internally just reading a varint, but this method exists - to make the calling code clearer. - - - - - The position within the current buffer (i.e. the next byte to read) - - - - - Size of the current buffer - - - - - If we are currently inside a length-delimited block, this is the number of - bytes in the buffer that are still available once we leave the delimited block. - - - - - The absolute position of the end of the current length-delimited block (including totalBytesRetired) - - - - - The total number of consumed before the start of the current buffer. The - total bytes read up to the current position can be computed as - totalBytesRetired + bufferPos. - - - - - The last tag we read. 0 indicates we've read to the end of the stream - (or haven't read anything yet). - - - - - The next tag, used to store the value read by PeekTag. - - - - - Internal-only property; when set to true, unknown fields will be discarded while parsing. - - - - - Internal-only property; provides extension identifiers to compatible messages while parsing. - - - - - Primitives for parsing protobuf wire format. - - - - - Reads a length for length-delimited data. - - - This is internally just reading a varint, but this method exists - to make the calling code clearer. - - - - - Parses the next tag. - If the end of logical stream was reached, an invalid tag of 0 is returned. - - - - - Peeks at the next tag in the stream. If it matches , - the tag is consumed and the method returns true; otherwise, the - stream is left in the original position and the method returns false. - - - - - Peeks at the next field tag. This is like calling , but the - tag is not consumed. (So a subsequent call to will return the - same value.) - - - - - Parses a raw varint. - - - - - Parses a raw Varint. If larger than 32 bits, discard the upper bits. - This method is optimised for the case where we've got lots of data in the buffer. - That means we can check the size just once, then just read directly from the buffer - without constant rechecking of the buffer length. - - - - - Parses a 32-bit little-endian integer. - - - - - Parses a 64-bit little-endian integer. - - - - - Parses a double value. - - - - - Parses a float value. - - - - - Reads a fixed size of bytes from the input. - - - the end of the stream or the current limit was reached - - - - - Reads and discards bytes. - - the end of the stream - or the current limit was reached - - - - Reads a string field value from the input. - - - - - Reads a bytes field value from the input. - - - - - Reads a UTF-8 string from the next "length" bytes. - - - the end of the stream or the current limit was reached - - - - - Reads a string assuming that it is spread across multiple spans in a . - - - - - Validates that the specified size doesn't exceed the current limit. If it does then remaining bytes - are skipped and an error is thrown. - - - - - Reads a varint from the input one byte at a time, so that it does not - read any bytes after the end of the varint. If you simply wrapped the - stream in a CodedInputStream and used ReadRawVarint32(Stream) - then you would probably end up reading past the end of the varint since - CodedInputStream buffers its input. - - - - - - - Decode a 32-bit value with ZigZag encoding. - - - ZigZag encodes signed integers into values that can be efficiently - encoded with varint. (Otherwise, negative values must be - sign-extended to 32 bits to be varint encoded, thus always taking - 5 bytes on the wire.) - - - - - Decode a 64-bit value with ZigZag encoding. - - - ZigZag encodes signed integers into values that can be efficiently - encoded with varint. (Otherwise, negative values must be - sign-extended to 64 bits to be varint encoded, thus always taking - 10 bytes on the wire.) - - - - - Checks whether there is known data available of the specified size remaining to parse. - When parsing from a Stream this can return false because we have no knowledge of the amount - of data remaining in the stream until it is read. - - - - - Checks whether there is known data available of the specified size remaining to parse - in the underlying data source. - When parsing from a Stream this will return false because we have no knowledge of the amount - of data remaining in the stream until it is read. - - - - - Read raw bytes of the specified length into a span. The amount of data available and the current limit should - be checked before calling this method. - - - - - Reading and skipping messages / groups - - - - - Skip a group. - - - - - Verifies that the last call to ReadTag() returned tag 0 - in other words, - we've reached the end of the stream when we expected to. - - The - tag read was not the one specified - - - - Fast parsing primitives for wrapper types - - - - - Helper methods for throwing exceptions when preconditions are not met. - - - This class is used internally and by generated code; it is not particularly - expected to be used from application code, although nothing prevents it - from being used that way. - - - - - Throws an ArgumentNullException if the given value is null, otherwise - return the value to the caller. - - - - - Throws an ArgumentNullException if the given value is null, otherwise - return the value to the caller. - - - This is equivalent to but without the type parameter - constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull - with a value type - but it gets in the way if either you want to use it with a nullable - value type, or you want to use it with an unconstrained type parameter. - - - - - Container for a set of custom options specified within a message, field etc. - - - - This type is publicly immutable, but internally mutable. It is only populated - by the descriptor parsing code - by the time any user code is able to see an instance, - it will be fully initialized. - - - If an option is requested using the incorrect method, an answer may still be returned: all - of the numeric types are represented internally using 64-bit integers, for example. It is up to - the caller to ensure that they make the appropriate method call for the option they're interested in. - Note that enum options are simply stored as integers, so the value should be fetched using - and then cast appropriately. - - - Repeated options are currently not supported. Asking for a single value of an option - which was actually repeated will return the last value, except for message types where - all the set values are merged together. - - - - - - Retrieves a Boolean value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a signed 32-bit integer value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a signed 64-bit integer value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves an unsigned 32-bit integer value for the specified option field, - assuming a fixed-length representation. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves an unsigned 64-bit integer value for the specified option field, - assuming a fixed-length representation. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a signed 32-bit integer value for the specified option field, - assuming a fixed-length representation. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a signed 64-bit integer value for the specified option field, - assuming a fixed-length representation. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a signed 32-bit integer value for the specified option field, - assuming a zigzag encoding. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a signed 64-bit integer value for the specified option field, - assuming a zigzag encoding. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves an unsigned 32-bit integer value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves an unsigned 64-bit integer value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a 32-bit floating point value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a 64-bit floating point value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a string value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a bytes value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - - Retrieves a message value for the specified option field. - - The field to fetch the value for. - The output variable to populate. - true if a suitable value for the field was found; false otherwise. - - - Holder for reflection information generated from google/protobuf/descriptor.proto - - - File descriptor for google/protobuf/descriptor.proto - - - - The protocol compiler can output a FileDescriptorSet containing the .proto - files it parses. - - - - Field number for the "file" field. - - - - Describes a complete .proto file. - - - - Field number for the "name" field. - - - - file name, relative to root of source tree - - - - Gets whether the "name" field is set - - - Clears the value of the "name" field - - - Field number for the "package" field. - - - - e.g. "foo", "foo.bar", etc. - - - - Gets whether the "package" field is set - - - Clears the value of the "package" field - - - Field number for the "dependency" field. - - - - Names of files imported by this file. - - - - Field number for the "public_dependency" field. - - - - Indexes of the public imported files in the dependency list above. - - - - Field number for the "weak_dependency" field. - - - - Indexes of the weak imported files in the dependency list. - For Google-internal migration only. Do not use. - - - - Field number for the "message_type" field. - - - - All top-level definitions in this file. - - - - Field number for the "enum_type" field. - - - Field number for the "service" field. - - - Field number for the "extension" field. - - - Field number for the "options" field. - - - Field number for the "source_code_info" field. - - - - This field contains optional information about the original source code. - You may safely remove this entire field without harming runtime - functionality of the descriptors -- the information is needed only by - development tools. - - - - Field number for the "syntax" field. - - - - The syntax of the proto file. - The supported values are "proto2" and "proto3". - - - - Gets whether the "syntax" field is set - - - Clears the value of the "syntax" field - - - - Describes a message type. - - - - Field number for the "name" field. - - - Gets whether the "name" field is set - - - Clears the value of the "name" field - - - Field number for the "field" field. - - - Field number for the "extension" field. - - - Field number for the "nested_type" field. - - - Field number for the "enum_type" field. - - - Field number for the "extension_range" field. - - - Field number for the "oneof_decl" field. - - - Field number for the "options" field. - - - Field number for the "reserved_range" field. - - - Field number for the "reserved_name" field. - - - - Reserved field names, which may not be used by fields in the same message. - A given name may only be reserved once. - - - - Container for nested types declared in the DescriptorProto message type. - - - Field number for the "start" field. - - - - Inclusive. - - - - Gets whether the "start" field is set - - - Clears the value of the "start" field - - - Field number for the "end" field. - - - - Exclusive. - - - - Gets whether the "end" field is set - - - Clears the value of the "end" field - - - Field number for the "options" field. - - - - Range of reserved tag numbers. Reserved tag numbers may not be used by - fields or extension ranges in the same message. Reserved ranges may - not overlap. - - - - Field number for the "start" field. - - - - Inclusive. - - - - Gets whether the "start" field is set - - - Clears the value of the "start" field - - - Field number for the "end" field. - - - - Exclusive. - - - - Gets whether the "end" field is set - - - Clears the value of the "end" field - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. See above. - - - - - Describes a field within a message. - - - - Field number for the "name" field. - - - Gets whether the "name" field is set - - - Clears the value of the "name" field - - - Field number for the "number" field. - - - Gets whether the "number" field is set - - - Clears the value of the "number" field - - - Field number for the "label" field. - - - Gets whether the "label" field is set - - - Clears the value of the "label" field - - - Field number for the "type" field. - - - - If type_name is set, this need not be set. If both this and type_name - are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. - - - - Gets whether the "type" field is set - - - Clears the value of the "type" field - - - Field number for the "type_name" field. - - - - For message and enum types, this is the name of the type. If the name - starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - rules are used to find the type (i.e. first the nested types within this - message are searched, then within the parent, on up to the root - namespace). - - - - Gets whether the "type_name" field is set - - - Clears the value of the "type_name" field - - - Field number for the "extendee" field. - - - - For extensions, this is the name of the type being extended. It is - resolved in the same manner as type_name. - - - - Gets whether the "extendee" field is set - - - Clears the value of the "extendee" field - - - Field number for the "default_value" field. - - - - For numeric types, contains the original text representation of the value. - For booleans, "true" or "false". - For strings, contains the default text contents (not escaped in any way). - For bytes, contains the C escaped value. All bytes >= 128 are escaped. - - - - Gets whether the "default_value" field is set - - - Clears the value of the "default_value" field - - - Field number for the "oneof_index" field. - - - - If set, gives the index of a oneof in the containing type's oneof_decl - list. This field is a member of that oneof. - - - - Gets whether the "oneof_index" field is set - - - Clears the value of the "oneof_index" field - - - Field number for the "json_name" field. - - - - JSON name of this field. The value is set by protocol compiler. If the - user has set a "json_name" option on this field, that option's value - will be used. Otherwise, it's deduced from the field's name by converting - it to camelCase. - - - - Gets whether the "json_name" field is set - - - Clears the value of the "json_name" field - - - Field number for the "options" field. - - - Field number for the "proto3_optional" field. - - - - If true, this is a proto3 "optional". When a proto3 field is optional, it - tracks presence regardless of field type. - - When proto3_optional is true, this field must be belong to a oneof to - signal to old proto3 clients that presence is tracked for this field. This - oneof is known as a "synthetic" oneof, and this field must be its sole - member (each proto3 optional field gets its own synthetic oneof). Synthetic - oneofs exist in the descriptor only, and do not generate any API. Synthetic - oneofs must be ordered after all "real" oneofs. - - For message fields, proto3_optional doesn't create any semantic change, - since non-repeated message fields always track presence. However it still - indicates the semantic detail of whether the user wrote "optional" or not. - This can be useful for round-tripping the .proto file. For consistency we - give message fields a synthetic oneof also, even though it is not required - to track presence. This is especially important because the parser can't - tell if a field is a message or an enum, so it must always create a - synthetic oneof. - - Proto2 optional fields do not set this flag, because they already indicate - optional with `LABEL_OPTIONAL`. - - - - Gets whether the "proto3_optional" field is set - - - Clears the value of the "proto3_optional" field - - - Container for nested types declared in the FieldDescriptorProto message type. - - - - 0 is reserved for errors. - Order is weird for historical reasons. - - - - - Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if - negative values are likely. - - - - - Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if - negative values are likely. - - - - - Tag-delimited aggregate. - Group type is deprecated and not supported in proto3. However, Proto3 - implementations should still be able to parse the group wire format and - treat group fields as unknown fields. - - - - - Length-delimited aggregate. - - - - - New in version 2. - - - - - Uses ZigZag encoding. - - - - - Uses ZigZag encoding. - - - - - 0 is reserved for errors - - - - - Describes a oneof. - - - - Field number for the "name" field. - - - Gets whether the "name" field is set - - - Clears the value of the "name" field - - - Field number for the "options" field. - - - - Describes an enum type. - - - - Field number for the "name" field. - - - Gets whether the "name" field is set - - - Clears the value of the "name" field - - - Field number for the "value" field. - - - Field number for the "options" field. - - - Field number for the "reserved_range" field. - - - - Range of reserved numeric values. Reserved numeric values may not be used - by enum values in the same enum declaration. Reserved ranges may not - overlap. - - - - Field number for the "reserved_name" field. - - - - Reserved enum value names, which may not be reused. A given name may only - be reserved once. - - - - Container for nested types declared in the EnumDescriptorProto message type. - - - - Range of reserved numeric values. Reserved values may not be used by - entries in the same enum. Reserved ranges may not overlap. - - Note that this is distinct from DescriptorProto.ReservedRange in that it - is inclusive such that it can appropriately represent the entire int32 - domain. - - - - Field number for the "start" field. - - - - Inclusive. - - - - Gets whether the "start" field is set - - - Clears the value of the "start" field - - - Field number for the "end" field. - - - - Inclusive. - - - - Gets whether the "end" field is set - - - Clears the value of the "end" field - - - - Describes a value within an enum. - - - - Field number for the "name" field. - - - Gets whether the "name" field is set - - - Clears the value of the "name" field - - - Field number for the "number" field. - - - Gets whether the "number" field is set - - - Clears the value of the "number" field - - - Field number for the "options" field. - - - - Describes a service. - - - - Field number for the "name" field. - - - Gets whether the "name" field is set - - - Clears the value of the "name" field - - - Field number for the "method" field. - - - Field number for the "options" field. - - - - Describes a method of a service. - - - - Field number for the "name" field. - - - Gets whether the "name" field is set - - - Clears the value of the "name" field - - - Field number for the "input_type" field. - - - - Input and output type names. These are resolved in the same way as - FieldDescriptorProto.type_name, but must refer to a message type. - - - - Gets whether the "input_type" field is set - - - Clears the value of the "input_type" field - - - Field number for the "output_type" field. - - - Gets whether the "output_type" field is set - - - Clears the value of the "output_type" field - - - Field number for the "options" field. - - - Field number for the "client_streaming" field. - - - - Identifies if client streams multiple client messages - - - - Gets whether the "client_streaming" field is set - - - Clears the value of the "client_streaming" field - - - Field number for the "server_streaming" field. - - - - Identifies if server streams multiple server messages - - - - Gets whether the "server_streaming" field is set - - - Clears the value of the "server_streaming" field - - - Field number for the "java_package" field. - - - - Sets the Java package where classes generated from this .proto will be - placed. By default, the proto package is used, but this is often - inappropriate because proto packages do not normally start with backwards - domain names. - - - - Gets whether the "java_package" field is set - - - Clears the value of the "java_package" field - - - Field number for the "java_outer_classname" field. - - - - Controls the name of the wrapper Java class generated for the .proto file. - That class will always contain the .proto file's getDescriptor() method as - well as any top-level extensions defined in the .proto file. - If java_multiple_files is disabled, then all the other classes from the - .proto file will be nested inside the single wrapper outer class. - - - - Gets whether the "java_outer_classname" field is set - - - Clears the value of the "java_outer_classname" field - - - Field number for the "java_multiple_files" field. - - - - If enabled, then the Java code generator will generate a separate .java - file for each top-level message, enum, and service defined in the .proto - file. Thus, these types will *not* be nested inside the wrapper class - named by java_outer_classname. However, the wrapper class will still be - generated to contain the file's getDescriptor() method as well as any - top-level extensions defined in the file. - - - - Gets whether the "java_multiple_files" field is set - - - Clears the value of the "java_multiple_files" field - - - Field number for the "java_generate_equals_and_hash" field. - - - - This option does nothing. - - - - Gets whether the "java_generate_equals_and_hash" field is set - - - Clears the value of the "java_generate_equals_and_hash" field - - - Field number for the "java_string_check_utf8" field. - - - - If set true, then the Java2 code generator will generate code that - throws an exception whenever an attempt is made to assign a non-UTF-8 - byte sequence to a string field. - Message reflection will do the same. - However, an extension field still accepts non-UTF-8 byte sequences. - This option has no effect on when used with the lite runtime. - - - - Gets whether the "java_string_check_utf8" field is set - - - Clears the value of the "java_string_check_utf8" field - - - Field number for the "optimize_for" field. - - - Gets whether the "optimize_for" field is set - - - Clears the value of the "optimize_for" field - - - Field number for the "go_package" field. - - - - Sets the Go package where structs generated from this .proto will be - placed. If omitted, the Go package will be derived from the following: - - The basename of the package import path, if provided. - - Otherwise, the package statement in the .proto file, if present. - - Otherwise, the basename of the .proto file, without extension. - - - - Gets whether the "go_package" field is set - - - Clears the value of the "go_package" field - - - Field number for the "cc_generic_services" field. - - - - Should generic services be generated in each language? "Generic" services - are not specific to any particular RPC system. They are generated by the - main code generators in each language (without additional plugins). - Generic services were the only kind of service generation supported by - early versions of google.protobuf. - - Generic services are now considered deprecated in favor of using plugins - that generate code specific to your particular RPC system. Therefore, - these default to false. Old code which depends on generic services should - explicitly set them to true. - - - - Gets whether the "cc_generic_services" field is set - - - Clears the value of the "cc_generic_services" field - - - Field number for the "java_generic_services" field. - - - Gets whether the "java_generic_services" field is set - - - Clears the value of the "java_generic_services" field - - - Field number for the "py_generic_services" field. - - - Gets whether the "py_generic_services" field is set - - - Clears the value of the "py_generic_services" field - - - Field number for the "php_generic_services" field. - - - Gets whether the "php_generic_services" field is set - - - Clears the value of the "php_generic_services" field - - - Field number for the "deprecated" field. - - - - Is this file deprecated? - Depending on the target platform, this can emit Deprecated annotations - for everything in the file, or it will be completely ignored; in the very - least, this is a formalization for deprecating files. - - - - Gets whether the "deprecated" field is set - - - Clears the value of the "deprecated" field - - - Field number for the "cc_enable_arenas" field. - - - - Enables the use of arenas for the proto messages in this file. This applies - only to generated classes for C++. - - - - Gets whether the "cc_enable_arenas" field is set - - - Clears the value of the "cc_enable_arenas" field - - - Field number for the "objc_class_prefix" field. - - - - Sets the objective c class prefix which is prepended to all objective c - generated classes from this .proto. There is no default. - - - - Gets whether the "objc_class_prefix" field is set - - - Clears the value of the "objc_class_prefix" field - - - Field number for the "csharp_namespace" field. - - - - Namespace for generated classes; defaults to the package. - - - - Gets whether the "csharp_namespace" field is set - - - Clears the value of the "csharp_namespace" field - - - Field number for the "swift_prefix" field. - - - - By default Swift generators will take the proto package and CamelCase it - replacing '.' with underscore and use that to prefix the types/symbols - defined. When this options is provided, they will use this value instead - to prefix the types/symbols defined. - - - - Gets whether the "swift_prefix" field is set - - - Clears the value of the "swift_prefix" field - - - Field number for the "php_class_prefix" field. - - - - Sets the php class prefix which is prepended to all php generated classes - from this .proto. Default is empty. - - - - Gets whether the "php_class_prefix" field is set - - - Clears the value of the "php_class_prefix" field - - - Field number for the "php_namespace" field. - - - - Use this option to change the namespace of php generated classes. Default - is empty. When this option is empty, the package name will be used for - determining the namespace. - - - - Gets whether the "php_namespace" field is set - - - Clears the value of the "php_namespace" field - - - Field number for the "php_metadata_namespace" field. - - - - Use this option to change the namespace of php generated metadata classes. - Default is empty. When this option is empty, the proto file name will be - used for determining the namespace. - - - - Gets whether the "php_metadata_namespace" field is set - - - Clears the value of the "php_metadata_namespace" field - - - Field number for the "ruby_package" field. - - - - Use this option to change the package of ruby generated classes. Default - is empty. When this option is not set, the package name will be used for - determining the ruby package. - - - - Gets whether the "ruby_package" field is set - - - Clears the value of the "ruby_package" field - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. - See the documentation for the "Options" section above. - - - - Container for nested types declared in the FileOptions message type. - - - - Generated classes can be optimized for speed or code size. - - - - - Generate complete code for parsing, serialization, - - - - - etc. - - - - - Generate code using MessageLite and the lite runtime. - - - - Field number for the "message_set_wire_format" field. - - - - Set true to use the old proto1 MessageSet wire format for extensions. - This is provided for backwards-compatibility with the MessageSet wire - format. You should not use this for any other reason: It's less - efficient, has fewer features, and is more complicated. - - The message must be defined exactly as follows: - message Foo { - option message_set_wire_format = true; - extensions 4 to max; - } - Note that the message cannot have any defined fields; MessageSets only - have extensions. - - All extensions of your type must be singular messages; e.g. they cannot - be int32s, enums, or repeated messages. - - Because this is an option, the above two restrictions are not enforced by - the protocol compiler. - - - - Gets whether the "message_set_wire_format" field is set - - - Clears the value of the "message_set_wire_format" field - - - Field number for the "no_standard_descriptor_accessor" field. - - - - Disables the generation of the standard "descriptor()" accessor, which can - conflict with a field of the same name. This is meant to make migration - from proto1 easier; new code should avoid fields named "descriptor". - - - - Gets whether the "no_standard_descriptor_accessor" field is set - - - Clears the value of the "no_standard_descriptor_accessor" field - - - Field number for the "deprecated" field. - - - - Is this message deprecated? - Depending on the target platform, this can emit Deprecated annotations - for the message, or it will be completely ignored; in the very least, - this is a formalization for deprecating messages. - - - - Gets whether the "deprecated" field is set - - - Clears the value of the "deprecated" field - - - Field number for the "map_entry" field. - - - - Whether the message is an automatically generated map entry type for the - maps field. - - For maps fields: - map<KeyType, ValueType> map_field = 1; - The parsed descriptor looks like: - message MapFieldEntry { - option map_entry = true; - optional KeyType key = 1; - optional ValueType value = 2; - } - repeated MapFieldEntry map_field = 1; - - Implementations may choose not to generate the map_entry=true message, but - use a native map in the target language to hold the keys and values. - The reflection APIs in such implementations still need to work as - if the field is a repeated message field. - - NOTE: Do not set the option in .proto files. Always use the maps syntax - instead. The option should only be implicitly set by the proto compiler - parser. - - - - Gets whether the "map_entry" field is set - - - Clears the value of the "map_entry" field - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. See above. - - - - Field number for the "ctype" field. - - - - The ctype option instructs the C++ code generator to use a different - representation of the field than it normally would. See the specific - options below. This option is not yet implemented in the open source - release -- sorry, we'll try to include it in a future version! - - - - Gets whether the "ctype" field is set - - - Clears the value of the "ctype" field - - - Field number for the "packed" field. - - - - The packed option can be enabled for repeated primitive fields to enable - a more efficient representation on the wire. Rather than repeatedly - writing the tag and type for each element, the entire array is encoded as - a single length-delimited blob. In proto3, only explicit setting it to - false will avoid using packed encoding. - - - - Gets whether the "packed" field is set - - - Clears the value of the "packed" field - - - Field number for the "jstype" field. - - - - The jstype option determines the JavaScript type used for values of the - field. The option is permitted only for 64 bit integral and fixed types - (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING - is represented as JavaScript string, which avoids loss of precision that - can happen when a large value is converted to a floating point JavaScript. - Specifying JS_NUMBER for the jstype causes the generated JavaScript code to - use the JavaScript "number" type. The behavior of the default option - JS_NORMAL is implementation dependent. - - This option is an enum to permit additional types to be added, e.g. - goog.math.Integer. - - - - Gets whether the "jstype" field is set - - - Clears the value of the "jstype" field - - - Field number for the "lazy" field. - - - - Should this field be parsed lazily? Lazy applies only to message-type - fields. It means that when the outer message is initially parsed, the - inner message's contents will not be parsed but instead stored in encoded - form. The inner message will actually be parsed when it is first accessed. - - This is only a hint. Implementations are free to choose whether to use - eager or lazy parsing regardless of the value of this option. However, - setting this option true suggests that the protocol author believes that - using lazy parsing on this field is worth the additional bookkeeping - overhead typically needed to implement it. - - This option does not affect the public interface of any generated code; - all method signatures remain the same. Furthermore, thread-safety of the - interface is not affected by this option; const methods remain safe to - call from multiple threads concurrently, while non-const methods continue - to require exclusive access. - - Note that implementations may choose not to check required fields within - a lazy sub-message. That is, calling IsInitialized() on the outer message - may return true even if the inner message has missing required fields. - This is necessary because otherwise the inner message would have to be - parsed in order to perform the check, defeating the purpose of lazy - parsing. An implementation which chooses not to check required fields - must be consistent about it. That is, for any particular sub-message, the - implementation must either *always* check its required fields, or *never* - check its required fields, regardless of whether or not the message has - been parsed. - - As of 2021, lazy does no correctness checks on the byte stream during - parsing. This may lead to crashes if and when an invalid byte stream is - finally parsed upon access. - - TODO(b/211906113): Enable validation on lazy fields. - - - - Gets whether the "lazy" field is set - - - Clears the value of the "lazy" field - - - Field number for the "unverified_lazy" field. - - - - unverified_lazy does no correctness checks on the byte stream. This should - only be used where lazy with verification is prohibitive for performance - reasons. - - - - Gets whether the "unverified_lazy" field is set - - - Clears the value of the "unverified_lazy" field - - - Field number for the "deprecated" field. - - - - Is this field deprecated? - Depending on the target platform, this can emit Deprecated annotations - for accessors, or it will be completely ignored; in the very least, this - is a formalization for deprecating fields. - - - - Gets whether the "deprecated" field is set - - - Clears the value of the "deprecated" field - - - Field number for the "weak" field. - - - - For Google-internal migration only. Do not use. - - - - Gets whether the "weak" field is set - - - Clears the value of the "weak" field - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. See above. - - - - Container for nested types declared in the FieldOptions message type. - - - - Default mode. - - - - - Use the default type. - - - - - Use JavaScript strings. - - - - - Use JavaScript numbers. - - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. See above. - - - - Field number for the "allow_alias" field. - - - - Set this option to true to allow mapping different tag names to the same - value. - - - - Gets whether the "allow_alias" field is set - - - Clears the value of the "allow_alias" field - - - Field number for the "deprecated" field. - - - - Is this enum deprecated? - Depending on the target platform, this can emit Deprecated annotations - for the enum, or it will be completely ignored; in the very least, this - is a formalization for deprecating enums. - - - - Gets whether the "deprecated" field is set - - - Clears the value of the "deprecated" field - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. See above. - - - - Field number for the "deprecated" field. - - - - Is this enum value deprecated? - Depending on the target platform, this can emit Deprecated annotations - for the enum value, or it will be completely ignored; in the very least, - this is a formalization for deprecating enum values. - - - - Gets whether the "deprecated" field is set - - - Clears the value of the "deprecated" field - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. See above. - - - - Field number for the "deprecated" field. - - - - Is this service deprecated? - Depending on the target platform, this can emit Deprecated annotations - for the service, or it will be completely ignored; in the very least, - this is a formalization for deprecating services. - - - - Gets whether the "deprecated" field is set - - - Clears the value of the "deprecated" field - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. See above. - - - - Field number for the "deprecated" field. - - - - Is this method deprecated? - Depending on the target platform, this can emit Deprecated annotations - for the method, or it will be completely ignored; in the very least, - this is a formalization for deprecating methods. - - - - Gets whether the "deprecated" field is set - - - Clears the value of the "deprecated" field - - - Field number for the "idempotency_level" field. - - - Gets whether the "idempotency_level" field is set - - - Clears the value of the "idempotency_level" field - - - Field number for the "uninterpreted_option" field. - - - - The parser stores options it doesn't recognize here. See above. - - - - Container for nested types declared in the MethodOptions message type. - - - - Is this method side-effect-free (or safe in HTTP parlance), or idempotent, - or neither? HTTP based RPC implementation may choose GET verb for safe - methods, and PUT verb for idempotent methods instead of the default POST. - - - - - implies idempotent - - - - - idempotent, but may have side effects - - - - - A message representing a option the parser does not recognize. This only - appears in options protos created by the compiler::Parser class. - DescriptorPool resolves these when building Descriptor objects. Therefore, - options protos in descriptor objects (e.g. returned by Descriptor::options(), - or produced by Descriptor::CopyTo()) will never have UninterpretedOptions - in them. - - - - Field number for the "name" field. - - - Field number for the "identifier_value" field. - - - - The value of the uninterpreted option, in whatever type the tokenizer - identified it as during parsing. Exactly one of these should be set. - - - - Gets whether the "identifier_value" field is set - - - Clears the value of the "identifier_value" field - - - Field number for the "positive_int_value" field. - - - Gets whether the "positive_int_value" field is set - - - Clears the value of the "positive_int_value" field - - - Field number for the "negative_int_value" field. - - - Gets whether the "negative_int_value" field is set - - - Clears the value of the "negative_int_value" field - - - Field number for the "double_value" field. - - - Gets whether the "double_value" field is set - - - Clears the value of the "double_value" field - - - Field number for the "string_value" field. - - - Gets whether the "string_value" field is set - - - Clears the value of the "string_value" field - - - Field number for the "aggregate_value" field. - - - Gets whether the "aggregate_value" field is set - - - Clears the value of the "aggregate_value" field - - - Container for nested types declared in the UninterpretedOption message type. - - - - The name of the uninterpreted option. Each string represents a segment in - a dot-separated name. is_extension is true iff a segment represents an - extension (denoted with parentheses in options specs in .proto files). - E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents - "foo.(bar.baz).moo". - - - - Field number for the "name_part" field. - - - Gets whether the "name_part" field is set - - - Clears the value of the "name_part" field - - - Field number for the "is_extension" field. - - - Gets whether the "is_extension" field is set - - - Clears the value of the "is_extension" field - - - - Encapsulates information about the original source file from which a - FileDescriptorProto was generated. - - - - Field number for the "location" field. - - - - A Location identifies a piece of source code in a .proto file which - corresponds to a particular definition. This information is intended - to be useful to IDEs, code indexers, documentation generators, and similar - tools. - - For example, say we have a file like: - message Foo { - optional string foo = 1; - } - Let's look at just the field definition: - optional string foo = 1; - ^ ^^ ^^ ^ ^^^ - a bc de f ghi - We have the following locations: - span path represents - [a,i) [ 4, 0, 2, 0 ] The whole field definition. - [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). - [c,d) [ 4, 0, 2, 0, 5 ] The type (string). - [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). - [g,h) [ 4, 0, 2, 0, 3 ] The number (1). - - Notes: - - A location may refer to a repeated field itself (i.e. not to any - particular index within it). This is used whenever a set of elements are - logically enclosed in a single code segment. For example, an entire - extend block (possibly containing multiple extension definitions) will - have an outer location whose path refers to the "extensions" repeated - field without an index. - - Multiple locations may have the same path. This happens when a single - logical declaration is spread out across multiple places. The most - obvious example is the "extend" block again -- there may be multiple - extend blocks in the same scope, each of which will have the same path. - - A location's span is not always a subset of its parent's span. For - example, the "extendee" of an extension declaration appears at the - beginning of the "extend" block and is shared by all extensions within - the block. - - Just because a location's span is a subset of some other location's span - does not mean that it is a descendant. For example, a "group" defines - both a type and a field in a single declaration. Thus, the locations - corresponding to the type and field and their components will overlap. - - Code which tries to interpret locations should probably be designed to - ignore those that it doesn't understand, as more types of locations could - be recorded in the future. - - - - Container for nested types declared in the SourceCodeInfo message type. - - - Field number for the "path" field. - - - - Identifies which part of the FileDescriptorProto was defined at this - location. - - Each element is a field number or an index. They form a path from - the root FileDescriptorProto to the place where the definition occurs. - For example, this path: - [ 4, 3, 2, 7, 1 ] - refers to: - file.message_type(3) // 4, 3 - .field(7) // 2, 7 - .name() // 1 - This is because FileDescriptorProto.message_type has field number 4: - repeated DescriptorProto message_type = 4; - and DescriptorProto.field has field number 2: - repeated FieldDescriptorProto field = 2; - and FieldDescriptorProto.name has field number 1: - optional string name = 1; - - Thus, the above path gives the location of a field name. If we removed - the last element: - [ 4, 3, 2, 7 ] - this path refers to the whole field declaration (from the beginning - of the label to the terminating semicolon). - - - - Field number for the "span" field. - - - - Always has exactly three or four elements: start line, start column, - end line (optional, otherwise assumed same as start line), end column. - These are packed into a single field for efficiency. Note that line - and column numbers are zero-based -- typically you will want to add - 1 to each before displaying to a user. - - - - Field number for the "leading_comments" field. - - - - If this SourceCodeInfo represents a complete declaration, these are any - comments appearing before and after the declaration which appear to be - attached to the declaration. - - A series of line comments appearing on consecutive lines, with no other - tokens appearing on those lines, will be treated as a single comment. - - leading_detached_comments will keep paragraphs of comments that appear - before (but not connected to) the current element. Each paragraph, - separated by empty lines, will be one comment element in the repeated - field. - - Only the comment content is provided; comment markers (e.g. //) are - stripped out. For block comments, leading whitespace and an asterisk - will be stripped from the beginning of each line other than the first. - Newlines are included in the output. - - Examples: - - optional int32 foo = 1; // Comment attached to foo. - // Comment attached to bar. - optional int32 bar = 2; - - optional string baz = 3; - // Comment attached to baz. - // Another line attached to baz. - - // Comment attached to moo. - // - // Another line attached to moo. - optional double moo = 4; - - // Detached comment for corge. This is not leading or trailing comments - // to moo or corge because there are blank lines separating it from - // both. - - // Detached comment for corge paragraph 2. - - optional string corge = 5; - /* Block comment attached - * to corge. Leading asterisks - * will be removed. */ - /* Block comment attached to - * grault. */ - optional int32 grault = 6; - - // ignored detached comments. - - - - Gets whether the "leading_comments" field is set - - - Clears the value of the "leading_comments" field - - - Field number for the "trailing_comments" field. - - - Gets whether the "trailing_comments" field is set - - - Clears the value of the "trailing_comments" field - - - Field number for the "leading_detached_comments" field. - - - - Describes the relationship between generated code and its original source - file. A GeneratedCodeInfo message is associated with only one generated - source file, but may contain references to different source .proto files. - - - - Field number for the "annotation" field. - - - - An Annotation connects some span of text in generated code to an element - of its generating .proto file. - - - - Container for nested types declared in the GeneratedCodeInfo message type. - - - Field number for the "path" field. - - - - Identifies the element in the original source .proto file. This field - is formatted the same as SourceCodeInfo.Location.path. - - - - Field number for the "source_file" field. - - - - Identifies the filesystem path to the original source .proto. - - - - Gets whether the "source_file" field is set - - - Clears the value of the "source_file" field - - - Field number for the "begin" field. - - - - Identifies the starting offset in bytes in the generated code - that relates to the identified object. - - - - Gets whether the "begin" field is set - - - Clears the value of the "begin" field - - - Field number for the "end" field. - - - - Identifies the ending offset in bytes in the generated code that - relates to the identified offset. The end offset should be one past - the last relevant byte (so the length of the text = end - begin). - - - - Gets whether the "end" field is set - - - Clears the value of the "end" field - - - - Base class for nearly all descriptors, providing common functionality. - - - - - The index of this descriptor within its parent descriptor. - - - This returns the index of this descriptor within its parent, for - this descriptor's type. (There can be duplicate values for different - types, e.g. one enum type with index 0 and one message type with index 0.) - - - - - Returns the name of the entity (field, message etc) being described. - - - - - The fully qualified name of the descriptor's target. - - - - - The file this descriptor was declared in. - - - - - The declaration information about the descriptor, or null if no declaration information - is available for this descriptor. - - - This information is typically only available for dynamically loaded descriptors, - for example within a protoc plugin where the full descriptors, including source info, - are passed to the code by protoc. - - - - - Retrieves the list of nested descriptors corresponding to the given field number, if any. - If the field is unknown or not a nested descriptor list, return null to terminate the search. - The default implementation returns null. - - - - - Provides additional information about the declaration of a descriptor, - such as source location and comments. - - - - - The descriptor this declaration relates to. - - - - - The start line of the declaration within the source file. This value is 1-based. - - - - - The start column of the declaration within the source file. This value is 1-based. - - - - - // The end line of the declaration within the source file. This value is 1-based. - - - - - The end column of the declaration within the source file. This value is 1-based, and - exclusive. (The final character of the declaration is on the column before this value.) - - - - - Comments appearing before the declaration. Never null, but may be empty. Multi-line comments - are represented as a newline-separated string. Leading whitespace and the comment marker ("//") - are removed from each line. - - - - - Comments appearing after the declaration. Never null, but may be empty. Multi-line comments - are represented as a newline-separated string. Leading whitespace and the comment marker ("//") - are removed from each line. - - - - - Comments appearing before the declaration, but separated from it by blank - lines. Each string represents a newline-separated paragraph of comments. - Leading whitespace and the comment marker ("//") are removed from each line. - The list is never null, but may be empty. Likewise each element is never null, but may be empty. - - - - - Contains lookup tables containing all the descriptors defined in a particular file. - - - - - Finds a symbol of the given name within the pool. - - The type of symbol to look for - Fully-qualified name to look up - The symbol with the given name and type, - or null if the symbol doesn't exist or has the wrong type - - - - Adds a package to the symbol tables. If a package by the same name - already exists, that is fine, but if some other kind of symbol - exists under the same name, an exception is thrown. If the package - has multiple components, this also adds the parent package(s). - - - - - Adds a symbol to the symbol table. - - The symbol already existed - in the symbol table. - - - - Verifies that the descriptor's name is valid (i.e. it contains - only letters, digits and underscores, and does not start with a digit). - - - - - - Returns the field with the given number in the given descriptor, - or null if it can't be found. - - - - - Adds a field to the fieldsByNumber table. - - A field with the same - containing type and number already exists. - - - - Adds an enum value to the enumValuesByNumber table. If an enum value - with the same type and number already exists, this method does nothing. - (This is allowed; the first value defined with the number takes precedence.) - - - - - Looks up a descriptor by name, relative to some other descriptor. - The name may be fully-qualified (with a leading '.'), partially-qualified, - or unqualified. C++-like name lookup semantics are used to search for the - matching descriptor. - - - This isn't heavily optimized, but it's only used during cross linking anyway. - If it starts being used more widely, we should look at performance more carefully. - - - - - Internal class containing utility methods when working with descriptors. - - - - - Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert - arrays. - - - - - Converts the given array into a read-only list, applying the specified conversion to - each input element. - - - - - Thrown when building descriptors fails because the source DescriptorProtos - are not valid. - - - - - The full name of the descriptor where the error occurred. - - - - - A human-readable description of the error. (The Message property - is made up of the descriptor's name and this description.) - - - - - Descriptor for an enum type in a .proto file. - - - - - Returns a clone of the underlying describing this enum. - Note that a copy is taken every time this method is called, so clients using it frequently - (and not modifying it) may want to cache the returned value. - - A protobuf representation of this enum descriptor. - - - - The brief name of the descriptor's target. - - - - - The CLR type for this enum. For generated code, this will be a CLR enum type. - - - - - If this is a nested type, get the outer descriptor, otherwise null. - - - - - An unmodifiable list of defined value descriptors for this enum. - - - - - Finds an enum value by number. If multiple enum values have the - same number, this returns the first defined value with that number. - If there is no value for the given number, this returns null. - - - - - Finds an enum value by name. - - The unqualified name of the value (e.g. "FOO"). - The value's descriptor, or null if not found. - - - - The (possibly empty) set of custom options for this enum. - - - - - The EnumOptions, defined in descriptor.proto. - If the options message is not present (i.e. there are no options), null is returned. - Custom options can be retrieved as extensions of the returned message. - NOTE: A defensive copy is created each time this property is retrieved. - - - - - Gets a single value enum option for this descriptor - - - - - Gets a repeated value enum option for this descriptor - - - - - Descriptor for a single enum value within an enum in a .proto file. - - - - - Returns a clone of the underlying describing this enum value. - Note that a copy is taken every time this method is called, so clients using it frequently - (and not modifying it) may want to cache the returned value. - - A protobuf representation of this enum value descriptor. - - - - Returns the name of the enum value described by this object. - - - - - Returns the number associated with this enum value. - - - - - Returns the enum descriptor that this value is part of. - - - - - The (possibly empty) set of custom options for this enum value. - - - - - The EnumValueOptions, defined in descriptor.proto. - If the options message is not present (i.e. there are no options), null is returned. - Custom options can be retrieved as extensions of the returned message. - NOTE: A defensive copy is created each time this property is retrieved. - - - - - Gets a single value enum value option for this descriptor - - - - - Gets a repeated value enum value option for this descriptor - - - - - A collection to simplify retrieving the descriptors of extensions in a descriptor for a message - - - - - Returns a readonly list of all the extensions defined in this type in - the order they were defined in the source .proto file - - - - - Returns a readonly list of all the extensions define in this type that extend - the provided descriptor type in the order they were defined in the source .proto file - - - - - Returns a readonly list of all the extensions define in this type that extend - the provided descriptor type in ascending field order - - - - - Base class for field accessors. - - - - - Descriptor for a field or extension within a message in a .proto file. - - - - - Get the field's containing message type, or null if it is a field defined at the top level of a file as an extension. - - - - - Returns the oneof containing this field, or null if it is not part of a oneof. - - - - - Returns the oneof containing this field if it's a "real" oneof, or null if either this - field is not part of a oneof, or the oneof is synthetic. - - - - - The effective JSON name for this field. This is usually the lower-camel-cased form of the field name, - but can be overridden using the json_name option in the .proto file. - - - - - The name of the property in the ContainingType.ClrType class. - - - - - Indicates whether this field supports presence, either implicitly (e.g. due to it being a message - type field) or explicitly via Has/Clear members. If this returns true, it is safe to call - and - on this field's accessor with a suitable message. - - - - - Returns a clone of the underlying describing this field. - Note that a copy is taken every time this method is called, so clients using it frequently - (and not modifying it) may want to cache the returned value. - - A protobuf representation of this field descriptor. - - - - An extension identifier for this field, or null if this field isn't an extension. - - - - - The brief name of the descriptor's target. - - - - - Returns the accessor for this field. - - - - While a describes the field, it does not provide - any way of obtaining or changing the value of the field within a specific message; - that is the responsibility of the accessor. - - - In descriptors for generated code, the value returned by this property will be non-null for all - regular fields. However, if a message containing a map field is introspected, the list of nested messages will include - an auto-generated nested key/value pair message for the field. This is not represented in any - generated type, and the value of the map field itself is represented by a dictionary in the - reflection API. There are never instances of those "hidden" messages, so no accessor is provided - and this property will return null. - - - In dynamically loaded descriptors, the value returned by this property will current be null; - if and when dynamic messages are supported, it will return a suitable accessor to work with - them. - - - - - - Maps a field type as included in the .proto file to a FieldType. - - - - - Returns true if this field is a repeated field; false otherwise. - - - - - Returns true if this field is a required field; false otherwise. - - - - - Returns true if this field is a map field; false otherwise. - - - - - Returns true if this field is a packed, repeated field; false otherwise. - - - - - Returns true if this field extends another message type; false otherwise. - - - - - Returns the type of the field. - - - - - Returns the field number declared in the proto file. - - - - - Compares this descriptor with another one, ordering in "canonical" order - which simply means ascending order by field number. - must be a field of the same type, i.e. the of - both fields must be the same. - - - - - For enum fields, returns the field's type. - - - - - For embedded message and group fields, returns the field's type. - - - - - For extension fields, returns the extended type - - - - - The (possibly empty) set of custom options for this field. - - - - - The FieldOptions, defined in descriptor.proto. - If the options message is not present (i.e. there are no options), null is returned. - Custom options can be retrieved as extensions of the returned message. - NOTE: A defensive copy is created each time this property is retrieved. - - - - - Gets a single value field option for this descriptor - - - - - Gets a repeated value field option for this descriptor - - - - - Look up and cross-link all field types etc. - - - - - Enumeration of all the possible field types. - - - - - The double field type. - - - - - The float field type. - - - - - The int64 field type. - - - - - The uint64 field type. - - - - - The int32 field type. - - - - - The fixed64 field type. - - - - - The fixed32 field type. - - - - - The bool field type. - - - - - The string field type. - - - - - The field type used for groups. - - - - - The field type used for message fields. - - - - - The bytes field type. - - - - - The uint32 field type. - - - - - The sfixed32 field type. - - - - - The sfixed64 field type. - - - - - The sint32 field type. - - - - - The sint64 field type. - - - - - The field type used for enum fields. - - - - - The syntax of a .proto file - - - - - Proto2 syntax - - - - - Proto3 syntax - - - - - An unknown declared syntax - - - - - Describes a .proto file, including everything defined within. - IDescriptor is implemented such that the File property returns this descriptor, - and the FullName is the same as the Name. - - - - - Computes the full name of a descriptor within this file, with an optional parent message. - - - - - Extracts public dependencies from direct dependencies. This is a static method despite its - first parameter, as the value we're in the middle of constructing is only used for exceptions. - - - - - The descriptor in its protocol message representation. - - - - - Returns a clone of the underlying describing this file. - Note that a copy is taken every time this method is called, so clients using it frequently - (and not modifying it) may want to cache the returned value. - - A protobuf representation of this file descriptor. - - - - The syntax of the file - - - - - The file name. - - - - - The package as declared in the .proto file. This may or may not - be equivalent to the .NET namespace of the generated classes. - - - - - Unmodifiable list of top-level message types declared in this file. - - - - - Unmodifiable list of top-level enum types declared in this file. - - - - - Unmodifiable list of top-level services declared in this file. - - - - - Unmodifiable list of top-level extensions declared in this file. - Note that some extensions may be incomplete (FieldDescriptor.Extension may be null) - if this descriptor was generated using a version of protoc that did not fully - support extensions in C#. - - - - - Unmodifiable list of this file's dependencies (imports). - - - - - Unmodifiable list of this file's public dependencies (public imports). - - - - - The original serialized binary form of this descriptor. - - - - - Implementation of IDescriptor.FullName - just returns the same as Name. - - - - - Implementation of IDescriptor.File - just returns this descriptor. - - - - - Pool containing symbol descriptors. - - - - - Finds a type (message, enum, service or extension) in the file by name. Does not find nested types. - - The unqualified type name to look for. - The type of descriptor to look for - The type's descriptor, or null if not found. - - - - Builds a FileDescriptor from its protocol buffer representation. - - The original serialized descriptor data. - We have only limited proto2 support, so serializing FileDescriptorProto - would not necessarily give us this. - The protocol message form of the FileDescriptor. - FileDescriptors corresponding to all of the - file's dependencies, in the exact order listed in the .proto file. May be null, - in which case it is treated as an empty array. - Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false). - Details about generated code, for the purposes of reflection. - If is not - a valid descriptor. This can occur for a number of reasons, such as a field - having an undefined type or because two messages were defined with the same name. - - - - Creates a descriptor for generated code. - - - This method is only designed to be used by the results of generating code with protoc, - which creates the appropriate dependencies etc. It has to be public because the generated - code is "external", but should not be called directly by end users. - - - - - Converts the given descriptor binary data into FileDescriptor objects. - Note: reflection using the returned FileDescriptors is not currently supported. - - The binary file descriptor proto data. Must not be null, and any - dependencies must come before the descriptor which depends on them. (If A depends on B, and B - depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible - with the order in which protoc provides descriptors to plugins. - The extension registry to use when parsing, or null if no extensions are required. - The file descriptors corresponding to . - - - - Converts the given descriptor binary data into FileDescriptor objects. - Note: reflection using the returned FileDescriptors is not currently supported. - - The binary file descriptor proto data. Must not be null, and any - dependencies must come before the descriptor which depends on them. (If A depends on B, and B - depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible - with the order in which protoc provides descriptors to plugins. - The file descriptors corresponding to . - - - - Returns a that represents this instance. - - - A that represents this instance. - - - - - Returns the file descriptor for descriptor.proto. - - - This is used for protos which take a direct dependency on descriptor.proto, typically for - annotations. While descriptor.proto is a proto2 file, it is built into the Google.Protobuf - runtime for reflection purposes. The messages are internal to the runtime as they would require - proto2 semantics for full support, but the file descriptor is available via this property. The - C# codegen in protoc automatically uses this property when it detects a dependency on descriptor.proto. - - - The file descriptor for descriptor.proto. - - - - - The (possibly empty) set of custom options for this file. - - - - - The FileOptions, defined in descriptor.proto. - If the options message is not present (i.e. there are no options), null is returned. - Custom options can be retrieved as extensions of the returned message. - NOTE: A defensive copy is created each time this property is retrieved. - - - - - Gets a single value file option for this descriptor - - - - - Gets a repeated value file option for this descriptor - - - - - Performs initialization for the given generic type argument. - - - This method is present for the sake of AOT compilers. It allows code (whether handwritten or generated) - to make calls into the reflection machinery of this library to express an intention to use that type - reflectively (e.g. for JSON parsing and formatting). The call itself does almost nothing, but AOT compilers - attempting to determine which generic type arguments need to be handled will spot the code path and act - accordingly. - - The type to force initialization for. - - - - Extra information provided by generated code when initializing a message or file descriptor. - These are constructed as required, and are not long-lived. Hand-written code should - never need to use this type. - - - - - Irrelevant for file descriptors; the CLR type for the message for message descriptors. - - - - - Irrelevant for file descriptors; the parser for message descriptors. - - - - - Irrelevant for file descriptors; the CLR property names (in message descriptor field order) - for fields in the message for message descriptors. - - - - - The extensions defined within this file/message descriptor - - - - - Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order) - for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo", - there will be a "FooCase" property and a "ClearFoo" method. - - - - - The reflection information for types within this file/message descriptor. Elements may be null - if there is no corresponding generated type, e.g. for map entry types. - - - - - The CLR types for enums within this file/message descriptor. - - - - - Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. - Each array parameter may be null, to indicate a lack of values. - The parameter order is designed to make it feasible to format the generated code readably. - - - - - Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. - Each array parameter may be null, to indicate a lack of values. - The parameter order is designed to make it feasible to format the generated code readably. - - - - - Creates a GeneratedClrTypeInfo for a file descriptor, with only types, enums, and extensions. - - - - - Creates a GeneratedClrTypeInfo for a file descriptor, with only types and enums. - - - - - Interface implemented by all descriptor types. - - - - - Returns the name of the entity (message, field etc) being described. - - - - - Returns the fully-qualified name of the entity being described. - - - - - Returns the descriptor for the .proto file that this entity is part of. - - - - - Allows fields to be reflectively accessed. - - - - - Returns the descriptor associated with this field. - - - - - Clears the field in the specified message. (For repeated fields, - this clears the list.) - - - - - Fetches the field value. For repeated values, this will be an - implementation. For map values, this will be an - implementation. - - - - - Indicates whether the field in the specified message is set. - For proto3 fields that aren't explicitly optional, this throws an - - - - - Mutator for single "simple" fields only. - - - Repeated fields are mutated by fetching the value and manipulating it as a list. - Map fields are mutated by fetching the value and manipulating it as a dictionary. - - The field is not a "simple" field. - - - - Accessor for map fields. - - - - - Describes a message type. - - - - - The brief name of the descriptor's target. - - - - - Returns a clone of the underlying describing this message. - Note that a copy is taken every time this method is called, so clients using it frequently - (and not modifying it) may want to cache the returned value. - - A protobuf representation of this message descriptor. - - - - The CLR type used to represent message instances from this descriptor. - - - - The value returned by this property will be non-null for all regular fields. However, - if a message containing a map field is introspected, the list of nested messages will include - an auto-generated nested key/value pair message for the field. This is not represented in any - generated type, so this property will return null in such cases. - - - For wrapper types ( and the like), the type returned here - will be the generated message type, not the native type used by reflection for fields of those types. Code - using reflection should call to determine whether a message descriptor represents - a wrapper type, and handle the result appropriately. - - - - - - A parser for this message type. - - - - As is not generic, this cannot be statically - typed to the relevant type, but it should produce objects of a type compatible with . - - - The value returned by this property will be non-null for all regular fields. However, - if a message containing a map field is introspected, the list of nested messages will include - an auto-generated nested key/value pair message for the field. No message parser object is created for - such messages, so this property will return null in such cases. - - - For wrapper types ( and the like), the parser returned here - will be the generated message type, not the native type used by reflection for fields of those types. Code - using reflection should call to determine whether a message descriptor represents - a wrapper type, and handle the result appropriately. - - - - - - Returns whether this message is one of the "well known types" which may have runtime/protoc support. - - - - - Returns whether this message is one of the "wrapper types" used for fields which represent primitive values - with the addition of presence. - - - - - If this is a nested type, get the outer descriptor, otherwise null. - - - - - A collection of fields, which can be retrieved by name or field number. - - - - - An unmodifiable list of extensions defined in this message's scope. - Note that some extensions may be incomplete (FieldDescriptor.Extension may be null) - if they are declared in a file generated using a version of protoc that did not fully - support extensions in C#. - - - - - An unmodifiable list of this message type's nested types. - - - - - An unmodifiable list of this message type's enum types. - - - - - An unmodifiable list of the "oneof" field collections in this message type. - All "real" oneofs (where returns false) - come before synthetic ones. - - - - - The number of real "oneof" descriptors in this message type. Every element in - with an index less than this will have a property value - of false; every element with an index greater than or equal to this will have a - property value of true. - - - - - Finds a field by field name. - - The unqualified name of the field (e.g. "foo"). - The field's descriptor, or null if not found. - - - - Finds a field by field number. - - The field number within this message type. - The field's descriptor, or null if not found. - - - - Finds a nested descriptor by name. The is valid for fields, nested - message types, oneofs and enums. - - The unqualified name of the descriptor, e.g. "Foo" - The descriptor, or null if not found. - - - - The (possibly empty) set of custom options for this message. - - - - - The MessageOptions, defined in descriptor.proto. - If the options message is not present (i.e. there are no options), null is returned. - Custom options can be retrieved as extensions of the returned message. - NOTE: A defensive copy is created each time this property is retrieved. - - - - - Gets a single value message option for this descriptor - - - - - Gets a repeated value message option for this descriptor - - - - - Looks up and cross-links all fields and nested types. - - - - - A collection to simplify retrieving the field accessor for a particular field. - - - - - Returns the fields in the message as an immutable list, in the order in which they - are declared in the source .proto file. - - - - - Returns the fields in the message as an immutable list, in ascending field number - order. Field numbers need not be contiguous, so there is no direct mapping from the - index in the list to the field number; to retrieve a field by field number, it is better - to use the indexer. - - - - - Returns a read-only dictionary mapping the field names in this message as they're available - in the JSON representation to the field descriptors. For example, a field foo_bar - in the message would result two entries, one with a key fooBar and one with a key - foo_bar, both referring to the same field. - - - - - Retrieves the descriptor for the field with the given number. - - Number of the field to retrieve the descriptor for - The accessor for the given field - The message descriptor does not contain a field - with the given number - - - - Retrieves the descriptor for the field with the given name. - - Name of the field to retrieve the descriptor for - The descriptor for the given field - The message descriptor does not contain a field - with the given name - - - - Describes a single method in a service. - - - - - The service this method belongs to. - - - - - The method's input type. - - - - - The method's input type. - - - - - Indicates if client streams multiple requests. - - - - - Indicates if server streams multiple responses. - - - - - The (possibly empty) set of custom options for this method. - - - - - The MethodOptions, defined in descriptor.proto. - If the options message is not present (i.e. there are no options), null is returned. - Custom options can be retrieved as extensions of the returned message. - NOTE: A defensive copy is created each time this property is retrieved. - - - - - Gets a single value method option for this descriptor - - - - - Gets a repeated value method option for this descriptor - - - - - Returns a clone of the underlying describing this method. - Note that a copy is taken every time this method is called, so clients using it frequently - (and not modifying it) may want to cache the returned value. - - A protobuf representation of this method descriptor. - - - - The brief name of the descriptor's target. - - - - - Reflection access for a oneof, allowing clear and "get case" actions. - - - - - Gets the descriptor for this oneof. - - - The descriptor of the oneof. - - - - - Clears the oneof in the specified message. - - - - - Indicates which field in the oneof is set for specified message - - - - - Describes a "oneof" field collection in a message type: a set of - fields of which at most one can be set in any particular message. - - - - - The brief name of the descriptor's target. - - - - - Returns a clone of the underlying describing this oneof. - Note that a copy is taken every time this method is called, so clients using it frequently - (and not modifying it) may want to cache the returned value. - - A protobuf representation of this oneof descriptor. - - - - Gets the message type containing this oneof. - - - The message type containing this oneof. - - - - - Gets the fields within this oneof, in declaration order. - - - The fields within this oneof, in declaration order. - - - - - Returns true if this oneof is a synthetic oneof containing a proto3 optional field; - false otherwise. - - - - - Gets an accessor for reflective access to the values associated with the oneof - in a particular message. - - - - In descriptors for generated code, the value returned by this property will always be non-null. - - - In dynamically loaded descriptors, the value returned by this property will current be null; - if and when dynamic messages are supported, it will return a suitable accessor to work with - them. - - - - The accessor used for reflective access. - - - - - The (possibly empty) set of custom options for this oneof. - - - - - The OneofOptions, defined in descriptor.proto. - If the options message is not present (i.e. there are no options), null is returned. - Custom options can be retrieved as extensions of the returned message. - NOTE: A defensive copy is created each time this property is retrieved. - - - - - Gets a single value oneof option for this descriptor - - - - - Gets a repeated value oneof option for this descriptor - - - - - Specifies the original name (in the .proto file) of a named element, - such as an enum value. - - - - - The name of the element in the .proto file. - - - - - If the name is preferred in the .proto file. - - - - - Constructs a new attribute instance for the given name. - - The name of the element in the .proto file. - - - - Represents a package in the symbol table. We use PackageDescriptors - just as placeholders so that someone cannot define, say, a message type - that has the same name as an existing package. - - - - - The methods in this class are somewhat evil, and should not be tampered with lightly. - Basically they allow the creation of relatively weakly typed delegates from MethodInfos - which are more strongly typed. They do this by creating an appropriate strongly typed - delegate from the MethodInfo, and then calling that within an anonymous method. - Mind-bending stuff (at least to your humble narrator) but the resulting delegates are - very fast compared with calling Invoke later on. - - - - - Empty Type[] used when calling GetProperty to force property instead of indexer fetching. - - - - - Creates a delegate which will cast the argument to the type that declares the method, - call the method on it, then convert the result to object. - - The method to create a delegate for, which must be declared in an IMessage - implementation. - - - - Creates a delegate which will cast the argument to the type that declares the method, - call the method on it, then convert the result to the specified type. The method is expected - to actually return an enum (because of where we're calling it - for oneof cases). Sometimes that - means we need some extra work to perform conversions. - - The method to create a delegate for, which must be declared in an IMessage - implementation. - - - - Creates a delegate which will execute the given method after casting the first argument to - the type that declares the method, and the second argument to the first parameter type of the method. - - The method to create a delegate for, which must be declared in an IMessage - implementation. - - - - Creates a delegate which will execute the given method after casting the first argument to - type that declares the method. - - The method to create a delegate for, which must be declared in an IMessage - implementation. - - - - Creates a delegate which will execute the given method after casting the first argument to - the type that declares the method, and the second argument to the first parameter type of the method. - - - - - Creates a reflection helper for the given type arguments. Currently these are created on demand - rather than cached; this will be "busy" when initially loading a message's descriptor, but after that - they can be garbage collected. We could cache them by type if that proves to be important, but creating - an object is pretty cheap. - - - - - Accessor for repeated fields. - - - - - Describes a service type. - - - - - The brief name of the descriptor's target. - - - - - Returns a clone of the underlying describing this service. - Note that a copy is taken every time this method is called, so clients using it frequently - (and not modifying it) may want to cache the returned value. - - A protobuf representation of this service descriptor. - - - - An unmodifiable list of methods in this service. - - - - - Finds a method by name. - - The unqualified name of the method (e.g. "Foo"). - The method's descriptor, or null if not found. - - - - The (possibly empty) set of custom options for this service. - - - - - The ServiceOptions, defined in descriptor.proto. - If the options message is not present (i.e. there are no options), null is returned. - Custom options can be retrieved as extensions of the returned message. - NOTE: A defensive copy is created each time this property is retrieved. - - - - - Gets a single value service option for this descriptor - - - - - Gets a repeated value service option for this descriptor - - - - - Accessor for single fields. - - - - - An immutable registry of types which can be looked up by their full name. - - - - - An empty type registry, containing no types. - - - - - Attempts to find a message descriptor by its full name. - - The full name of the message, which is the dot-separated - combination of package, containing messages and message name - The message descriptor corresponding to or null - if there is no such message descriptor. - - - - Creates a type registry from the specified set of file descriptors. - - - This is a convenience overload for - to allow calls such as TypeRegistry.FromFiles(descriptor1, descriptor2). - - The set of files to include in the registry. Must not contain null values. - A type registry for the given files. - - - - Creates a type registry from the specified set of file descriptors. - - - All message types within all the specified files are added to the registry, and - the dependencies of the specified files are also added, recursively. - - The set of files to include in the registry. Must not contain null values. - A type registry for the given files. - - - - Creates a type registry from the file descriptor parents of the specified set of message descriptors. - - - This is a convenience overload for - to allow calls such as TypeRegistry.FromFiles(descriptor1, descriptor2). - - The set of message descriptors to use to identify file descriptors to include in the registry. - Must not contain null values. - A type registry for the given files. - - - - Creates a type registry from the file descriptor parents of the specified set of message descriptors. - - - The specified message descriptors are only used to identify their file descriptors; the returned registry - contains all the types within the file descriptors which contain the specified message descriptors (and - the dependencies of those files), not just the specified messages. - - The set of message descriptors to use to identify file descriptors to include in the registry. - Must not contain null values. - A type registry for the given files. - - - - Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls. - - - - - Abstraction for reading from a stream / read only sequence. - Parsing from the buffer is a loop of reading from current buffer / refreshing the buffer once done. - - - - - Initialize an instance with a coded input stream. - This approach is faster than using a constructor because the instance to initialize is passed by reference - and we can write directly into it without copying. - - - - - Initialize an instance with a read only sequence. - This approach is faster than using a constructor because the instance to initialize is passed by reference - and we can write directly into it without copying. - - - - - Sets currentLimit to (current position) + byteLimit. This is called - when descending into a length-delimited embedded message. The previous - limit is returned. - - The old limit. - - - - Discards the current limit, returning the previous limit. - - - - - Returns whether or not all the data before the limit has been read. - - - - - - Returns true if the stream has reached the end of the input. This is the - case if either the end of the underlying input source has been reached or - the stream has reached a limit created using PushLimit. - - - - - Represents a single field in an UnknownFieldSet. - - An UnknownField consists of four lists of values. The lists correspond - to the four "wire types" used in the protocol buffer binary format. - Normally, only one of the four lists will contain any values, since it - is impossible to define a valid message type that declares two different - types for the same field number. However, the code is designed to allow - for the case where the same unknown field number is encountered using - multiple different wire types. - - - - - - Creates a new UnknownField. - - - - - Checks if two unknown field are equal. - - - - - Get the hash code of the unknown field. - - - - - Serializes the field, including the field number, and writes it to - - - The unknown field number. - The write context to write to. - - - - Computes the number of bytes required to encode this field, including field - number. - - - - - Merge the values in into this field. For each list - of values, 's values are append to the ones in this - field. - - - - - Returns a new list containing all of the given specified values from - both the and lists. - If is null and is null or empty, - null is returned. Otherwise, either a new list is created (if - is null) or the elements of are added to . - - - - - Adds a varint value. - - - - - Adds a fixed32 value. - - - - - Adds a fixed64 value. - - - - - Adds a length-delimited value. - - - - - Adds to the , creating - a new list if is null. The list is returned - either - the original reference or the new list. - - - - - Used to keep track of fields which were seen when parsing a protocol message - but whose field numbers or types are unrecognized. This most frequently - occurs when new fields are added to a message type and then messages containing - those fields are read by old software that was built before the new types were - added. - - Most users will never need to use this class directly. - - - - - Creates a new UnknownFieldSet. - - - - - Checks whether or not the given field number is present in the set. - - - - - Serializes the set and writes it to . - - - - - Serializes the set and writes it to . - - - - - Gets the number of bytes required to encode this set. - - - - - Checks if two unknown field sets are equal. - - - - - Gets the unknown field set's hash code. - - - - - Adds a field to the set. If a field with the same number already exists, it - is replaced. - - - - - Parse a single field from and merge it - into this set. - - The parse context from which to read the field - false if the tag is an "end group" tag, true otherwise - - - - Create a new UnknownFieldSet if unknownFields is null. - Parse a single field from and merge it - into unknownFields. If is configured to discard unknown fields, - will be returned as-is and the field will be skipped. - - The UnknownFieldSet which need to be merged - The coded input stream containing the field - The merged UnknownFieldSet - - - - Create a new UnknownFieldSet if unknownFields is null. - Parse a single field from and merge it - into unknownFields. If is configured to discard unknown fields, - will be returned as-is and the field will be skipped. - - The UnknownFieldSet which need to be merged - The parse context from which to read the field - The merged UnknownFieldSet - - - - Merges the fields from into this set. - If a field number exists in both sets, the values in - will be appended to the values in this set. - - - - - Created a new UnknownFieldSet to if - needed and merges the fields from into the first set. - If a field number exists in both sets, the values in - will be appended to the values in this set. - - - - - Adds a field to the unknown field set. If a field with the same - number already exists, the two are merged. - - - - - Clone an unknown field set from . - - - - - Provides a number of unsafe byte operations to be used by advanced applications with high performance - requirements. These methods are referred to as "unsafe" due to the fact that they potentially expose - the backing buffer of a to the application. - - - - The methods in this class should only be called if it is guaranteed that the buffer backing the - will never change! Mutation of a can lead to unexpected - and undesirable consequences in your application, and will likely be difficult to debug. Proceed with caution! - - - This can have a number of significant side affects that have spooky-action-at-a-distance-like behavior. In - particular, if the bytes value changes out from under a Protocol Buffer: - - - - serialization may throw - - - serialization may succeed but the wrong bytes may be written out - - - objects that are normally immutable (such as ByteString) are no longer immutable - - - hashCode may be incorrect - - - - - - - Constructs a new from the given bytes. The bytes are not copied, - and must not be modified while the is in use. - This API is experimental and subject to change. - - - - Holder for reflection information generated from google/protobuf/any.proto - - - File descriptor for google/protobuf/any.proto - - - - `Any` contains an arbitrary serialized protocol buffer message along with a - URL that describes the type of the serialized message. - - Protobuf library provides support to pack/unpack Any values in the form - of utility functions or additional generated methods of the Any type. - - Example 1: Pack and unpack a message in C++. - - Foo foo = ...; - Any any; - any.PackFrom(foo); - ... - if (any.UnpackTo(&foo)) { - ... - } - - Example 2: Pack and unpack a message in Java. - - Foo foo = ...; - Any any = Any.pack(foo); - ... - if (any.is(Foo.class)) { - foo = any.unpack(Foo.class); - } - - Example 3: Pack and unpack a message in Python. - - foo = Foo(...) - any = Any() - any.Pack(foo) - ... - if any.Is(Foo.DESCRIPTOR): - any.Unpack(foo) - ... - - Example 4: Pack and unpack a message in Go - - foo := &pb.Foo{...} - any, err := anypb.New(foo) - if err != nil { - ... - } - ... - foo := &pb.Foo{} - if err := any.UnmarshalTo(foo); err != nil { - ... - } - - The pack methods provided by protobuf library will by default use - 'type.googleapis.com/full.type.name' as the type URL and the unpack - methods only use the fully qualified type name after the last '/' - in the type URL, for example "foo.bar.com/x/y.z" will yield type - name "y.z". - - JSON - - The JSON representation of an `Any` value uses the regular - representation of the deserialized, embedded message, with an - additional field `@type` which contains the type URL. Example: - - package google.profile; - message Person { - string first_name = 1; - string last_name = 2; - } - - { - "@type": "type.googleapis.com/google.profile.Person", - "firstName": <string>, - "lastName": <string> - } - - If the embedded message type is well-known and has a custom JSON - representation, that representation will be embedded adding a field - `value` which holds the custom JSON in addition to the `@type` - field. Example (for message [google.protobuf.Duration][]): - - { - "@type": "type.googleapis.com/google.protobuf.Duration", - "value": "1.212s" - } - - - - Field number for the "type_url" field. - - - - A URL/resource name that uniquely identifies the type of the serialized - protocol buffer message. This string must contain at least - one "/" character. The last segment of the URL's path must represent - the fully qualified name of the type (as in - `path/google.protobuf.Duration`). The name should be in a canonical form - (e.g., leading "." is not accepted). - - In practice, teams usually precompile into the binary all types that they - expect it to use in the context of Any. However, for URLs which use the - scheme `http`, `https`, or no scheme, one can optionally set up a type - server that maps type URLs to message definitions as follows: - - * If no scheme is provided, `https` is assumed. - * An HTTP GET on the URL must yield a [google.protobuf.Type][] - value in binary format, or produce an error. - * Applications are allowed to cache lookup results based on the - URL, or have them precompiled into a binary to avoid any - lookup. Therefore, binary compatibility needs to be preserved - on changes to types. (Use versioned type names to manage - breaking changes.) - - Note: this functionality is not currently available in the official - protobuf release, and it is not used for type URLs beginning with - type.googleapis.com. - - Schemes other than `http`, `https` (or the empty scheme) might be - used with implementation specific semantics. - - - - Field number for the "value" field. - - - - Must be a valid serialized protocol buffer of the above specified type. - - - - - Retrieves the type name for a type URL, matching the - of the packed message type. - - - - This is always just the last part of the URL, after the final slash. No validation of - anything before the trailing slash is performed. If the type URL does not include a slash, - an empty string is returned rather than an exception being thrown; this won't match any types, - and the calling code is probably in a better position to give a meaningful error. - - - There is no handling of fragments or queries at the moment. - - - The URL to extract the type name from - The type name - - - - Returns a bool indictating whether this Any message is of the target message type - - The descriptor of the message type - true if the type name matches the descriptor's full name or false otherwise - - - - Unpacks the content of this Any message into the target message type, - which must match the type URL within this Any message. - - The type of message to unpack the content into. - The unpacked message. - The target message type doesn't match the type URL in this message - - - - Attempts to unpack the content of this Any message into the target message type, - if it matches the type URL within this Any message. - - The type of message to attempt to unpack the content into. - true if the message was successfully unpacked; false if the type name didn't match - - - - Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com". - - The message to pack. - An Any message with the content and type URL of . - - - - Packs the specified message into an Any message using the specified type URL prefix. - - The message to pack. - The prefix for the type URL. - An Any message with the content and type URL of . - - - Holder for reflection information generated from google/protobuf/api.proto - - - File descriptor for google/protobuf/api.proto - - - - Api is a light-weight descriptor for an API Interface. - - Interfaces are also described as "protocol buffer services" in some contexts, - such as by the "service" keyword in a .proto file, but they are different - from API Services, which represent a concrete implementation of an interface - as opposed to simply a description of methods and bindings. They are also - sometimes simply referred to as "APIs" in other contexts, such as the name of - this message itself. See https://cloud.google.com/apis/design/glossary for - detailed terminology. - - - - Field number for the "name" field. - - - - The fully qualified name of this interface, including package name - followed by the interface's simple name. - - - - Field number for the "methods" field. - - - - The methods of this interface, in unspecified order. - - - - Field number for the "options" field. - - - - Any metadata attached to the interface. - - - - Field number for the "version" field. - - - - A version string for this interface. If specified, must have the form - `major-version.minor-version`, as in `1.10`. If the minor version is - omitted, it defaults to zero. If the entire version field is empty, the - major version is derived from the package name, as outlined below. If the - field is not empty, the version in the package name will be verified to be - consistent with what is provided here. - - The versioning schema uses [semantic - versioning](http://semver.org) where the major version number - indicates a breaking change and the minor version an additive, - non-breaking change. Both version numbers are signals to users - what to expect from different versions, and should be carefully - chosen based on the product plan. - - The major version is also reflected in the package name of the - interface, which must end in `v<major-version>`, as in - `google.feature.v1`. For major versions 0 and 1, the suffix can - be omitted. Zero major versions must only be used for - experimental, non-GA interfaces. - - - - Field number for the "source_context" field. - - - - Source context for the protocol buffer service represented by this - message. - - - - Field number for the "mixins" field. - - - - Included interfaces. See [Mixin][]. - - - - Field number for the "syntax" field. - - - - The source syntax of the service. - - - - - Method represents a method of an API interface. - - - - Field number for the "name" field. - - - - The simple name of this method. - - - - Field number for the "request_type_url" field. - - - - A URL of the input message type. - - - - Field number for the "request_streaming" field. - - - - If true, the request is streamed. - - - - Field number for the "response_type_url" field. - - - - The URL of the output message type. - - - - Field number for the "response_streaming" field. - - - - If true, the response is streamed. - - - - Field number for the "options" field. - - - - Any metadata attached to the method. - - - - Field number for the "syntax" field. - - - - The source syntax of this method. - - - - - Declares an API Interface to be included in this interface. The including - interface must redeclare all the methods from the included interface, but - documentation and options are inherited as follows: - - - If after comment and whitespace stripping, the documentation - string of the redeclared method is empty, it will be inherited - from the original method. - - - Each annotation belonging to the service config (http, - visibility) which is not set in the redeclared method will be - inherited. - - - If an http annotation is inherited, the path pattern will be - modified as follows. Any version prefix will be replaced by the - version of the including interface plus the [root][] path if - specified. - - Example of a simple mixin: - - package google.acl.v1; - service AccessControl { - // Get the underlying ACL object. - rpc GetAcl(GetAclRequest) returns (Acl) { - option (google.api.http).get = "/v1/{resource=**}:getAcl"; - } - } - - package google.storage.v2; - service Storage { - rpc GetAcl(GetAclRequest) returns (Acl); - - // Get a data record. - rpc GetData(GetDataRequest) returns (Data) { - option (google.api.http).get = "/v2/{resource=**}"; - } - } - - Example of a mixin configuration: - - apis: - - name: google.storage.v2.Storage - mixins: - - name: google.acl.v1.AccessControl - - The mixin construct implies that all methods in `AccessControl` are - also declared with same name and request/response types in - `Storage`. A documentation generator or annotation processor will - see the effective `Storage.GetAcl` method after inheriting - documentation and annotations as follows: - - service Storage { - // Get the underlying ACL object. - rpc GetAcl(GetAclRequest) returns (Acl) { - option (google.api.http).get = "/v2/{resource=**}:getAcl"; - } - ... - } - - Note how the version in the path pattern changed from `v1` to `v2`. - - If the `root` field in the mixin is specified, it should be a - relative path under which inherited HTTP paths are placed. Example: - - apis: - - name: google.storage.v2.Storage - mixins: - - name: google.acl.v1.AccessControl - root: acls - - This implies the following inherited HTTP annotation: - - service Storage { - // Get the underlying ACL object. - rpc GetAcl(GetAclRequest) returns (Acl) { - option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; - } - ... - } - - - - Field number for the "name" field. - - - - The fully qualified name of the interface which is included. - - - - Field number for the "root" field. - - - - If non-empty specifies a path under which inherited HTTP paths - are rooted. - - - - Holder for reflection information generated from google/protobuf/duration.proto - - - File descriptor for google/protobuf/duration.proto - - - - A Duration represents a signed, fixed-length span of time represented - as a count of seconds and fractions of seconds at nanosecond - resolution. It is independent of any calendar and concepts like "day" - or "month". It is related to Timestamp in that the difference between - two Timestamp values is a Duration and it can be added or subtracted - from a Timestamp. Range is approximately +-10,000 years. - - # Examples - - Example 1: Compute Duration from two Timestamps in pseudo code. - - Timestamp start = ...; - Timestamp end = ...; - Duration duration = ...; - - duration.seconds = end.seconds - start.seconds; - duration.nanos = end.nanos - start.nanos; - - if (duration.seconds < 0 && duration.nanos > 0) { - duration.seconds += 1; - duration.nanos -= 1000000000; - } else if (duration.seconds > 0 && duration.nanos < 0) { - duration.seconds -= 1; - duration.nanos += 1000000000; - } - - Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. - - Timestamp start = ...; - Duration duration = ...; - Timestamp end = ...; - - end.seconds = start.seconds + duration.seconds; - end.nanos = start.nanos + duration.nanos; - - if (end.nanos < 0) { - end.seconds -= 1; - end.nanos += 1000000000; - } else if (end.nanos >= 1000000000) { - end.seconds += 1; - end.nanos -= 1000000000; - } - - Example 3: Compute Duration from datetime.timedelta in Python. - - td = datetime.timedelta(days=3, minutes=10) - duration = Duration() - duration.FromTimedelta(td) - - # JSON Mapping - - In JSON format, the Duration type is encoded as a string rather than an - object, where the string ends in the suffix "s" (indicating seconds) and - is preceded by the number of seconds, with nanoseconds expressed as - fractional seconds. For example, 3 seconds with 0 nanoseconds should be - encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should - be expressed in JSON format as "3.000000001s", and 3 seconds and 1 - microsecond should be expressed in JSON format as "3.000001s". - - - - Field number for the "seconds" field. - - - - Signed seconds of the span of time. Must be from -315,576,000,000 - to +315,576,000,000 inclusive. Note: these bounds are computed from: - 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years - - - - Field number for the "nanos" field. - - - - Signed fractions of a second at nanosecond resolution of the span - of time. Durations less than one second are represented with a 0 - `seconds` field and a positive or negative `nanos` field. For durations - of one second or more, a non-zero value for the `nanos` field must be - of the same sign as the `seconds` field. Must be from -999,999,999 - to +999,999,999 inclusive. - - - - - The number of nanoseconds in a second. - - - - - The number of nanoseconds in a BCL tick (as used by and ). - - - - - The maximum permitted number of seconds. - - - - - The minimum permitted number of seconds. - - - - - Converts this to a . - - If the duration is not a precise number of ticks, it is truncated towards 0. - The value of this duration, as a TimeSpan. - This value isn't a valid normalized duration, as - described in the documentation. - - - - Converts the given to a . - - The TimeSpan to convert. - The value of the given TimeSpan, as a Duration. - - - - Returns the result of negating the duration. For example, the negation of 5 minutes is -5 minutes. - - The duration to negate. Must not be null. - The negated value of this duration. - - - - Adds the two specified values together. - - The first value to add. Must not be null. - The second value to add. Must not be null. - - - - - Subtracts one from another. - - The duration to subtract from. Must not be null. - The duration to subtract. Must not be null. - The difference between the two specified durations. - - - - Creates a duration with the normalized values from the given number of seconds and - nanoseconds, conforming with the description in the proto file. - - - - - Converts a duration specified in seconds/nanoseconds to a string. - - - If the value is a normalized duration in the range described in duration.proto, - is ignored. Otherwise, if the parameter is true, - a JSON object with a warning is returned; if it is false, an is thrown. - - Seconds portion of the duration. - Nanoseconds portion of the duration. - Determines the handling of non-normalized values - The represented duration is invalid, and is false. - - - - Returns a string representation of this for diagnostic purposes. - - - Normally the returned value will be a JSON string value (including leading and trailing quotes) but - when the value is non-normalized or out of range, a JSON object representation will be returned - instead, including a warning. This is to avoid exceptions being thrown when trying to - diagnose problems - the regular JSON formatter will still throw an exception for non-normalized - values. - - A string representation of this value. - - - - Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which - case no "." is appended), or 3 6 or 9 digits. This is internal for use in Timestamp as well - as Duration. - - - - Holder for reflection information generated from google/protobuf/empty.proto - - - File descriptor for google/protobuf/empty.proto - - - - A generic empty message that you can re-use to avoid defining duplicated - empty messages in your APIs. A typical example is to use it as the request - or the response type of an API method. For instance: - - service Foo { - rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); - } - - - - Holder for reflection information generated from google/protobuf/field_mask.proto - - - File descriptor for google/protobuf/field_mask.proto - - - - `FieldMask` represents a set of symbolic field paths, for example: - - paths: "f.a" - paths: "f.b.d" - - Here `f` represents a field in some root message, `a` and `b` - fields in the message found in `f`, and `d` a field found in the - message in `f.b`. - - Field masks are used to specify a subset of fields that should be - returned by a get operation or modified by an update operation. - Field masks also have a custom JSON encoding (see below). - - # Field Masks in Projections - - When used in the context of a projection, a response message or - sub-message is filtered by the API to only contain those fields as - specified in the mask. For example, if the mask in the previous - example is applied to a response message as follows: - - f { - a : 22 - b { - d : 1 - x : 2 - } - y : 13 - } - z: 8 - - The result will not contain specific values for fields x,y and z - (their value will be set to the default, and omitted in proto text - output): - - f { - a : 22 - b { - d : 1 - } - } - - A repeated field is not allowed except at the last position of a - paths string. - - If a FieldMask object is not present in a get operation, the - operation applies to all fields (as if a FieldMask of all fields - had been specified). - - Note that a field mask does not necessarily apply to the - top-level response message. In case of a REST get operation, the - field mask applies directly to the response, but in case of a REST - list operation, the mask instead applies to each individual message - in the returned resource list. In case of a REST custom method, - other definitions may be used. Where the mask applies will be - clearly documented together with its declaration in the API. In - any case, the effect on the returned resource/resources is required - behavior for APIs. - - # Field Masks in Update Operations - - A field mask in update operations specifies which fields of the - targeted resource are going to be updated. The API is required - to only change the values of the fields as specified in the mask - and leave the others untouched. If a resource is passed in to - describe the updated values, the API ignores the values of all - fields not covered by the mask. - - If a repeated field is specified for an update operation, new values will - be appended to the existing repeated field in the target resource. Note that - a repeated field is only allowed in the last position of a `paths` string. - - If a sub-message is specified in the last position of the field mask for an - update operation, then new value will be merged into the existing sub-message - in the target resource. - - For example, given the target message: - - f { - b { - d: 1 - x: 2 - } - c: [1] - } - - And an update message: - - f { - b { - d: 10 - } - c: [2] - } - - then if the field mask is: - - paths: ["f.b", "f.c"] - - then the result will be: - - f { - b { - d: 10 - x: 2 - } - c: [1, 2] - } - - An implementation may provide options to override this default behavior for - repeated and message fields. - - In order to reset a field's value to the default, the field must - be in the mask and set to the default value in the provided resource. - Hence, in order to reset all fields of a resource, provide a default - instance of the resource and set all fields in the mask, or do - not provide a mask as described below. - - If a field mask is not present on update, the operation applies to - all fields (as if a field mask of all fields has been specified). - Note that in the presence of schema evolution, this may mean that - fields the client does not know and has therefore not filled into - the request will be reset to their default. If this is unwanted - behavior, a specific service may require a client to always specify - a field mask, producing an error if not. - - As with get operations, the location of the resource which - describes the updated values in the request message depends on the - operation kind. In any case, the effect of the field mask is - required to be honored by the API. - - ## Considerations for HTTP REST - - The HTTP kind of an update operation which uses a field mask must - be set to PATCH instead of PUT in order to satisfy HTTP semantics - (PUT must only be used for full updates). - - # JSON Encoding of Field Masks - - In JSON, a field mask is encoded as a single string where paths are - separated by a comma. Fields name in each path are converted - to/from lower-camel naming conventions. - - As an example, consider the following message declarations: - - message Profile { - User user = 1; - Photo photo = 2; - } - message User { - string display_name = 1; - string address = 2; - } - - In proto a field mask for `Profile` may look as such: - - mask { - paths: "user.display_name" - paths: "photo" - } - - In JSON, the same mask is represented as below: - - { - mask: "user.displayName,photo" - } - - # Field Masks and Oneof Fields - - Field masks treat fields in oneofs just as regular fields. Consider the - following message: - - message SampleMessage { - oneof test_oneof { - string name = 4; - SubMessage sub_message = 9; - } - } - - The field mask can be: - - mask { - paths: "name" - } - - Or: - - mask { - paths: "sub_message" - } - - Note that oneof type names ("test_oneof" in this case) cannot be used in - paths. - - ## Field Mask Verification - - The implementation of any API method which has a FieldMask type field in the - request should verify the included field paths, and return an - `INVALID_ARGUMENT` error if any path is unmappable. - - - - Field number for the "paths" field. - - - - The set of field mask paths. - - - - - Converts a field mask specified by paths to a string. - - - If the value is a normalized duration in the range described in field_mask.proto, - is ignored. Otherwise, if the parameter is true, - a JSON object with a warning is returned; if it is false, an is thrown. - - Paths in the field mask - Determines the handling of non-normalized values - The represented field mask is invalid, and is false. - - - - Returns a string representation of this for diagnostic purposes. - - - Normally the returned value will be a JSON string value (including leading and trailing quotes) but - when the value is non-normalized or out of range, a JSON object representation will be returned - instead, including a warning. This is to avoid exceptions being thrown when trying to - diagnose problems - the regular JSON formatter will still throw an exception for non-normalized - values. - - A string representation of this value. - - - - Parses from a string to a FieldMask. - - - - - Parses from a string to a FieldMask and validates all field paths. - - The type to validate the field paths against. - - - - Constructs a FieldMask for a list of field paths in a certain type. - - The type to validate the field paths against. - - - - Constructs a FieldMask from the passed field numbers. - - The type to validate the field paths against. - - - - Constructs a FieldMask from the passed field numbers. - - The type to validate the field paths against. - - - - Checks whether the given path is valid for a field mask. - - true if the path is valid; false otherwise - - - - Checks whether paths in a given fields mask are valid. - - The type to validate the field paths against. - - - - Checks whether paths in a given fields mask are valid. - - - - - Checks whether a given field path is valid. - - The type to validate the field paths against. - - - - Checks whether paths in a given fields mask are valid. - - - - - Converts this FieldMask to its canonical form. In the canonical form of a - FieldMask, all field paths are sorted alphabetically and redundant field - paths are removed. - - - - - Creates a union of two or more FieldMasks. - - - - - Calculates the intersection of two FieldMasks. - - - - - Merges fields specified by this FieldMask from one message to another with the - specified merge options. - - - - - Merges fields specified by this FieldMask from one message to another. - - - - - Options to customize merging behavior. - - - - - Whether to replace message fields(i.e., discard existing content in - destination message fields) when merging. - Default behavior is to merge the source message field into the - destination message field. - - - - - Whether to replace repeated fields (i.e., discard existing content in - destination repeated fields) when merging. - Default behavior is to append elements from source repeated field to the - destination repeated field. - - - - - Whether to replace primitive (non-repeated and non-message) fields in - destination message fields with the source primitive fields (i.e., if the - field is set in the source, the value is copied to the - destination; if the field is unset in the source, the field is cleared - from the destination) when merging. - - Default behavior is to always set the value of the source primitive - field to the destination primitive field, and if the source field is - unset, the default value of the source field is copied to the - destination. - - - - Holder for reflection information generated from google/protobuf/source_context.proto - - - File descriptor for google/protobuf/source_context.proto - - - - `SourceContext` represents information about the source of a - protobuf element, like the file in which it is defined. - - - - Field number for the "file_name" field. - - - - The path-qualified name of the .proto file that contained the associated - protobuf element. For example: `"google/protobuf/source_context.proto"`. - - - - Holder for reflection information generated from google/protobuf/struct.proto - - - File descriptor for google/protobuf/struct.proto - - - - `NullValue` is a singleton enumeration to represent the null value for the - `Value` type union. - - The JSON representation for `NullValue` is JSON `null`. - - - - - Null value. - - - - - `Struct` represents a structured data value, consisting of fields - which map to dynamically typed values. In some languages, `Struct` - might be supported by a native representation. For example, in - scripting languages like JS a struct is represented as an - object. The details of that representation are described together - with the proto support for the language. - - The JSON representation for `Struct` is JSON object. - - - - Field number for the "fields" field. - - - - Unordered map of dynamically typed values. - - - - - `Value` represents a dynamically typed value which can be either - null, a number, a string, a boolean, a recursive struct value, or a - list of values. A producer of value is expected to set one of these - variants. Absence of any variant indicates an error. - - The JSON representation for `Value` is JSON value. - - - - Field number for the "null_value" field. - - - - Represents a null value. - - - - Field number for the "number_value" field. - - - - Represents a double value. - - - - Field number for the "string_value" field. - - - - Represents a string value. - - - - Field number for the "bool_value" field. - - - - Represents a boolean value. - - - - Field number for the "struct_value" field. - - - - Represents a structured value. - - - - Field number for the "list_value" field. - - - - Represents a repeated `Value`. - - - - Enum of possible cases for the "kind" oneof. - - - - Convenience method to create a Value message with a string value. - - Value to set for the StringValue property. - A newly-created Value message with the given value. - - - - Convenience method to create a Value message with a number value. - - Value to set for the NumberValue property. - A newly-created Value message with the given value. - - - - Convenience method to create a Value message with a Boolean value. - - Value to set for the BoolValue property. - A newly-created Value message with the given value. - - - - Convenience method to create a Value message with a null initial value. - - A newly-created Value message a null initial value. - - - - Convenience method to create a Value message with an initial list of values. - - The values provided are not cloned; the references are copied directly. - A newly-created Value message an initial list value. - - - - Convenience method to create a Value message with an initial struct value - - The value provided is not cloned; the reference is copied directly. - A newly-created Value message an initial struct value. - - - - `ListValue` is a wrapper around a repeated field of values. - - The JSON representation for `ListValue` is JSON array. - - - - Field number for the "values" field. - - - - Repeated field of dynamically typed values. - - - - - Extension methods on BCL time-related types, converting to protobuf types. - - - - - Converts the given to a . - - The date and time to convert to a timestamp. - The value has a other than Utc. - The converted timestamp. - - - - Converts the given to a - - The offset is taken into consideration when converting the value (so the same instant in time - is represented) but is not a separate part of the resulting value. In other words, there is no - roundtrip operation to retrieve the original DateTimeOffset. - The date and time (with UTC offset) to convert to a timestamp. - The converted timestamp. - - - - Converts the given to a . - - The time span to convert. - The converted duration. - - - Holder for reflection information generated from google/protobuf/timestamp.proto - - - File descriptor for google/protobuf/timestamp.proto - - - - A Timestamp represents a point in time independent of any time zone or local - calendar, encoded as a count of seconds and fractions of seconds at - nanosecond resolution. The count is relative to an epoch at UTC midnight on - January 1, 1970, in the proleptic Gregorian calendar which extends the - Gregorian calendar backwards to year one. - - All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap - second table is needed for interpretation, using a [24-hour linear - smear](https://developers.google.com/time/smear). - - The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By - restricting to that range, we ensure that we can convert to and from [RFC - 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. - - # Examples - - Example 1: Compute Timestamp from POSIX `time()`. - - Timestamp timestamp; - timestamp.set_seconds(time(NULL)); - timestamp.set_nanos(0); - - Example 2: Compute Timestamp from POSIX `gettimeofday()`. - - struct timeval tv; - gettimeofday(&tv, NULL); - - Timestamp timestamp; - timestamp.set_seconds(tv.tv_sec); - timestamp.set_nanos(tv.tv_usec * 1000); - - Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. - - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; - - // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z - // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. - Timestamp timestamp; - timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); - timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); - - Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. - - long millis = System.currentTimeMillis(); - - Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) - .setNanos((int) ((millis % 1000) * 1000000)).build(); - - Example 5: Compute Timestamp from Java `Instant.now()`. - - Instant now = Instant.now(); - - Timestamp timestamp = - Timestamp.newBuilder().setSeconds(now.getEpochSecond()) - .setNanos(now.getNano()).build(); - - Example 6: Compute Timestamp from current time in Python. - - timestamp = Timestamp() - timestamp.GetCurrentTime() - - # JSON Mapping - - In JSON format, the Timestamp type is encoded as a string in the - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the - format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" - where {year} is always expressed using four digits while {month}, {day}, - {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional - seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), - are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone - is required. A proto3 JSON serializer should always use UTC (as indicated by - "Z") when printing the Timestamp type and a proto3 JSON parser should be - able to accept both UTC and other timezones (as indicated by an offset). - - For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past - 01:30 UTC on January 15, 2017. - - In JavaScript, one can convert a Date object to this format using the - standard - [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) - method. In Python, a standard `datetime.datetime` object can be converted - to this format using - [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with - the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use - the Joda Time's [`ISODateTimeFormat.dateTime()`]( - http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D - ) to obtain a formatter capable of generating timestamps in this format. - - - - Field number for the "seconds" field. - - - - Represents seconds of UTC time since Unix epoch - 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - 9999-12-31T23:59:59Z inclusive. - - - - Field number for the "nanos" field. - - - - Non-negative fractions of a second at nanosecond resolution. Negative - second values with fractions must still have non-negative nanos values - that count forward in time. Must be from 0 to 999,999,999 - inclusive. - - - - - Returns the difference between one and another, as a . - - The timestamp to subtract from. Must not be null. - The timestamp to subtract. Must not be null. - The difference between the two specified timestamps. - - - - Adds a to a , to obtain another Timestamp. - - The timestamp to add the duration to. Must not be null. - The duration to add. Must not be null. - The result of adding the duration to the timestamp. - - - - Subtracts a from a , to obtain another Timestamp. - - The timestamp to subtract the duration from. Must not be null. - The duration to subtract. - The result of subtracting the duration from the timestamp. - - - - Converts this timestamp into a . - - - The resulting DateTime will always have a Kind of Utc. - If the timestamp is not a precise number of ticks, it will be truncated towards the start - of time. For example, a timestamp with a value of 99 will result in a - value precisely on a second. - - This timestamp as a DateTime. - The timestamp contains invalid values; either it is - incorrectly normalized or is outside the valid range. - - - - Converts this timestamp into a . - - - The resulting DateTimeOffset will always have an Offset of zero. - If the timestamp is not a precise number of ticks, it will be truncated towards the start - of time. For example, a timestamp with a value of 99 will result in a - value precisely on a second. - - This timestamp as a DateTimeOffset. - The timestamp contains invalid values; either it is - incorrectly normalized or is outside the valid range. - - - - Converts the specified to a . - - - The Kind of is not DateTimeKind.Utc. - The converted timestamp. - - - - Converts the given to a - - The offset is taken into consideration when converting the value (so the same instant in time - is represented) but is not a separate part of the resulting value. In other words, there is no - roundtrip operation to retrieve the original DateTimeOffset. - The date and time (with UTC offset) to convert to a timestamp. - The converted timestamp. - - - - Converts a timestamp specified in seconds/nanoseconds to a string. - - - If the value is a normalized duration in the range described in timestamp.proto, - is ignored. Otherwise, if the parameter is true, - a JSON object with a warning is returned; if it is false, an is thrown. - - Seconds portion of the duration. - Nanoseconds portion of the duration. - Determines the handling of non-normalized values - The represented duration is invalid, and is false. - - - - Given another timestamp, returns 0 if the timestamps are equivalent, -1 if this timestamp precedes the other, and 1 otherwise - - - Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. - - Timestamp to compare - an integer indicating whether this timestamp precedes or follows the other - - - - Compares two timestamps and returns whether the first is less than (chronologically precedes) the second - - - Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. - - - - true if a precedes b - - - - Compares two timestamps and returns whether the first is greater than (chronologically follows) the second - - - Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. - - - - true if a follows b - - - - Compares two timestamps and returns whether the first is less than (chronologically precedes) the second - - - Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. - - - - true if a precedes b - - - - Compares two timestamps and returns whether the first is greater than (chronologically follows) the second - - - Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. - - - - true if a follows b - - - - Returns whether two timestamps are equivalent - - - Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. - - - - true if the two timestamps refer to the same nanosecond - - - - Returns whether two timestamps differ - - - Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. - - - - true if the two timestamps differ - - - - Returns a string representation of this for diagnostic purposes. - - - Normally the returned value will be a JSON string value (including leading and trailing quotes) but - when the value is non-normalized or out of range, a JSON object representation will be returned - instead, including a warning. This is to avoid exceptions being thrown when trying to - diagnose problems - the regular JSON formatter will still throw an exception for non-normalized - values. - - A string representation of this value. - - - Holder for reflection information generated from google/protobuf/type.proto - - - File descriptor for google/protobuf/type.proto - - - - The syntax in which a protocol buffer element is defined. - - - - - Syntax `proto2`. - - - - - Syntax `proto3`. - - - - - A protocol buffer message type. - - - - Field number for the "name" field. - - - - The fully qualified message name. - - - - Field number for the "fields" field. - - - - The list of fields. - - - - Field number for the "oneofs" field. - - - - The list of types appearing in `oneof` definitions in this type. - - - - Field number for the "options" field. - - - - The protocol buffer options. - - - - Field number for the "source_context" field. - - - - The source context. - - - - Field number for the "syntax" field. - - - - The source syntax. - - - - - A single field of a message type. - - - - Field number for the "kind" field. - - - - The field type. - - - - Field number for the "cardinality" field. - - - - The field cardinality. - - - - Field number for the "number" field. - - - - The field number. - - - - Field number for the "name" field. - - - - The field name. - - - - Field number for the "type_url" field. - - - - The field type URL, without the scheme, for message or enumeration - types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. - - - - Field number for the "oneof_index" field. - - - - The index of the field type in `Type.oneofs`, for message or enumeration - types. The first type has index 1; zero means the type is not in the list. - - - - Field number for the "packed" field. - - - - Whether to use alternative packed wire representation. - - - - Field number for the "options" field. - - - - The protocol buffer options. - - - - Field number for the "json_name" field. - - - - The field JSON name. - - - - Field number for the "default_value" field. - - - - The string value of the default value of this field. Proto2 syntax only. - - - - Container for nested types declared in the Field message type. - - - - Basic field types. - - - - - Field type unknown. - - - - - Field type double. - - - - - Field type float. - - - - - Field type int64. - - - - - Field type uint64. - - - - - Field type int32. - - - - - Field type fixed64. - - - - - Field type fixed32. - - - - - Field type bool. - - - - - Field type string. - - - - - Field type group. Proto2 syntax only, and deprecated. - - - - - Field type message. - - - - - Field type bytes. - - - - - Field type uint32. - - - - - Field type enum. - - - - - Field type sfixed32. - - - - - Field type sfixed64. - - - - - Field type sint32. - - - - - Field type sint64. - - - - - Whether a field is optional, required, or repeated. - - - - - For fields with unknown cardinality. - - - - - For optional fields. - - - - - For required fields. Proto2 syntax only. - - - - - For repeated fields. - - - - - Enum type definition. - - - - Field number for the "name" field. - - - - Enum type name. - - - - Field number for the "enumvalue" field. - - - - Enum value definitions. - - - - Field number for the "options" field. - - - - Protocol buffer options. - - - - Field number for the "source_context" field. - - - - The source context. - - - - Field number for the "syntax" field. - - - - The source syntax. - - - - - Enum value definition. - - - - Field number for the "name" field. - - - - Enum value name. - - - - Field number for the "number" field. - - - - Enum value number. - - - - Field number for the "options" field. - - - - Protocol buffer options. - - - - - A protocol buffer option, which can be attached to a message, field, - enumeration, etc. - - - - Field number for the "name" field. - - - - The option's name. For protobuf built-in options (options defined in - descriptor.proto), this is the short name. For example, `"map_entry"`. - For custom options, it should be the fully-qualified name. For example, - `"google.api.http"`. - - - - Field number for the "value" field. - - - - The option's value packed in an Any message. If the value is a primitive, - the corresponding wrapper type defined in google/protobuf/wrappers.proto - should be used. If the value is an enum, it should be stored as an int32 - value using the google.protobuf.Int32Value type. - - - - Holder for reflection information generated from google/protobuf/wrappers.proto - - - File descriptor for google/protobuf/wrappers.proto - - - - Field number for the single "value" field in all wrapper types. - - - - - Wrapper message for `double`. - - The JSON representation for `DoubleValue` is JSON number. - - - - Field number for the "value" field. - - - - The double value. - - - - - Wrapper message for `float`. - - The JSON representation for `FloatValue` is JSON number. - - - - Field number for the "value" field. - - - - The float value. - - - - - Wrapper message for `int64`. - - The JSON representation for `Int64Value` is JSON string. - - - - Field number for the "value" field. - - - - The int64 value. - - - - - Wrapper message for `uint64`. - - The JSON representation for `UInt64Value` is JSON string. - - - - Field number for the "value" field. - - - - The uint64 value. - - - - - Wrapper message for `int32`. - - The JSON representation for `Int32Value` is JSON number. - - - - Field number for the "value" field. - - - - The int32 value. - - - - - Wrapper message for `uint32`. - - The JSON representation for `UInt32Value` is JSON number. - - - - Field number for the "value" field. - - - - The uint32 value. - - - - - Wrapper message for `bool`. - - The JSON representation for `BoolValue` is JSON `true` and `false`. - - - - Field number for the "value" field. - - - - The bool value. - - - - - Wrapper message for `string`. - - The JSON representation for `StringValue` is JSON string. - - - - Field number for the "value" field. - - - - The string value. - - - - - Wrapper message for `bytes`. - - The JSON representation for `BytesValue` is JSON string. - - - - Field number for the "value" field. - - - - The bytes value. - - - - - This class is used internally by the Protocol Buffer Library and generated - message implementations. It is public only for the sake of those generated - messages. Others should not use this class directly. - - This class contains constants and helper functions useful for dealing with - the Protocol Buffer wire format. - - - - - - Wire types within protobuf encoding. - - - - - Variable-length integer. - - - - - A fixed-length 64-bit value. - - - - - A length-delimited value, i.e. a length followed by that many bytes of data. - - - - - A "start group" value - - - - - An "end group" value - - - - - A fixed-length 32-bit value. - - - - - Given a tag value, determines the wire type (lower 3 bits). - - - - - Given a tag value, determines the field number (the upper 29 bits). - - - - - Makes a tag value given a field number and wire type. - - - - - Abstraction for writing to a steam / IBufferWriter - - - - - Initialize an instance with a coded output stream. - This approach is faster than using a constructor because the instance to initialize is passed by reference - and we can write directly into it without copying. - - - - - Initialize an instance with a buffer writer. - This approach is faster than using a constructor because the instance to initialize is passed by reference - and we can write directly into it without copying. - - - - - Initialize an instance with a buffer represented by a single span (i.e. buffer cannot be refreshed) - This approach is faster than using a constructor because the instance to initialize is passed by reference - and we can write directly into it without copying. - - - - - Verifies that SpaceLeft returns zero. - - - - - If writing to a flat array, returns the space left in the array. Otherwise, - throws an InvalidOperationException. - - - - - An opaque struct that represents the current serialization state and is passed along - as the serialization proceeds. - All the public methods are intended to be invoked only by the generated code, - users should never invoke them directly. - - - - - Creates a WriteContext instance from CodedOutputStream. - WARNING: internally this copies the CodedOutputStream's state, so after done with the WriteContext, - the CodedOutputStream's state needs to be updated. - - - - - Writes a double field value, without a tag. - - The value to write - - - - Writes a float field value, without a tag. - - The value to write - - - - Writes a uint64 field value, without a tag. - - The value to write - - - - Writes an int64 field value, without a tag. - - The value to write - - - - Writes an int32 field value, without a tag. - - The value to write - - - - Writes a fixed64 field value, without a tag. - - The value to write - - - - Writes a fixed32 field value, without a tag. - - The value to write - - - - Writes a bool field value, without a tag. - - The value to write - - - - Writes a string field value, without a tag. - The data is length-prefixed. - - The value to write - - - - Writes a message, without a tag. - The data is length-prefixed. - - The value to write - - - - Writes a group, without a tag, to the stream. - - The value to write - - - - Write a byte string, without a tag, to the stream. - The data is length-prefixed. - - The value to write - - - - Writes a uint32 value, without a tag. - - The value to write - - - - Writes an enum value, without a tag. - - The value to write - - - - Writes an sfixed32 value, without a tag. - - The value to write. - - - - Writes an sfixed64 value, without a tag. - - The value to write - - - - Writes an sint32 value, without a tag. - - The value to write - - - - Writes an sint64 value, without a tag. - - The value to write - - - - Writes a length (in bytes) for length-delimited data. - - - This method simply writes a rawint, but exists for clarity in calling code. - - Length value, in bytes. - - - - Encodes and writes a tag. - - The number of the field to write the tag for - The wire format type of the tag to write - - - - Writes an already-encoded tag. - - The encoded tag - - - - Writes the given single-byte tag. - - The encoded tag - - - - Writes the given two-byte tag. - - The first byte of the encoded tag - The second byte of the encoded tag - - - - Writes the given three-byte tag. - - The first byte of the encoded tag - The second byte of the encoded tag - The third byte of the encoded tag - - - - Writes the given four-byte tag. - - The first byte of the encoded tag - The second byte of the encoded tag - The third byte of the encoded tag - The fourth byte of the encoded tag - - - - Writes the given five-byte tag. - - The first byte of the encoded tag - The second byte of the encoded tag - The third byte of the encoded tag - The fourth byte of the encoded tag - The fifth byte of the encoded tag - - - - Primitives for encoding protobuf wire format. - - - - - Writes a double field value, without a tag, to the stream. - - - - - Writes a float field value, without a tag, to the stream. - - - - - Writes a uint64 field value, without a tag, to the stream. - - - - - Writes an int64 field value, without a tag, to the stream. - - - - - Writes an int32 field value, without a tag, to the stream. - - - - - Writes a fixed64 field value, without a tag, to the stream. - - - - - Writes a fixed32 field value, without a tag, to the stream. - - - - - Writes a bool field value, without a tag, to the stream. - - - - - Writes a string field value, without a tag, to the stream. - The data is length-prefixed. - - - - - Given a QWORD which represents a buffer of 4 ASCII chars in machine-endian order, - narrows each WORD to a BYTE, then writes the 4-byte result to the output buffer - also in machine-endian order. - - - - - Write a byte string, without a tag, to the stream. - The data is length-prefixed. - - - - - Writes a uint32 value, without a tag, to the stream. - - - - - Writes an enum value, without a tag, to the stream. - - - - - Writes an sfixed32 value, without a tag, to the stream. - - - - - Writes an sfixed64 value, without a tag, to the stream. - - - - - Writes an sint32 value, without a tag, to the stream. - - - - - Writes an sint64 value, without a tag, to the stream. - - - - - Writes a length (in bytes) for length-delimited data. - - - This method simply writes a rawint, but exists for clarity in calling code. - - - - - Writes a 32 bit value as a varint. The fast route is taken when - there's enough buffer space left to whizz through without checking - for each byte; otherwise, we resort to calling WriteRawByte each time. - - - - - Writes out an array of bytes. - - - - - Writes out part of an array of bytes. - - - - - Writes out part of an array of bytes. - - - - - Encodes and writes a tag. - - - - - Writes an already-encoded tag. - - - - - Writes the given single-byte tag directly to the stream. - - - - - Writes the given two-byte tag directly to the stream. - - - - - Writes the given three-byte tag directly to the stream. - - - - - Writes the given four-byte tag directly to the stream. - - - - - Writes the given five-byte tag directly to the stream. - - - - - Encode a 32-bit value with ZigZag encoding. - - - ZigZag encodes signed integers into values that can be efficiently - encoded with varint. (Otherwise, negative values must be - sign-extended to 64 bits to be varint encoded, thus always taking - 10 bytes on the wire.) - - - - - Encode a 64-bit value with ZigZag encoding. - - - ZigZag encodes signed integers into values that can be efficiently - encoded with varint. (Otherwise, negative values must be - sign-extended to 64 bits to be varint encoded, thus always taking - 10 bytes on the wire.) - - - - - Writing messages / groups. - - - - - Writes a message, without a tag. - The data is length-prefixed. - - - - - Writes a group, without a tag. - - - - - Writes a message, without a tag. - Message will be written without a length prefix. - - - - - Indicates that certain members on a specified are accessed dynamically, - for example through . - - - This allows tools to understand which members are being accessed during the execution - of a program. - - This attribute is valid on members whose type is or . - - When this attribute is applied to a location of type , the assumption is - that the string represents a fully qualified type name. - - When this attribute is applied to a class, interface, or struct, the members specified - can be accessed dynamically on instances returned from calling - on instances of that class, interface, or struct. - - If the attribute is applied to a method it's treated as a special case and it implies - the attribute should be applied to the "this" parameter of the method. As such the attribute - should only be used on instance methods of types assignable to System.Type (or string, but no methods - will use it there). - - - - - Initializes a new instance of the class - with the specified member types. - - The types of members dynamically accessed. - - - - Gets the which specifies the type - of members dynamically accessed. - - - - - Specifies the types of members that are dynamically accessed. - - This enumeration has a attribute that allows a - bitwise combination of its member values. - - - - - Specifies no members. - - - - - Specifies the default, parameterless public constructor. - - - - - Specifies all public constructors. - - - - - Specifies all non-public constructors. - - - - - Specifies all public methods. - - - - - Specifies all non-public methods. - - - - - Specifies all public fields. - - - - - Specifies all non-public fields. - - - - - Specifies all public nested types. - - - - - Specifies all non-public nested types. - - - - - Specifies all public properties. - - - - - Specifies all non-public properties. - - - - - Specifies all public events. - - - - - Specifies all non-public events. - - - - - Specifies all interfaces implemented by the type. - - - - - Specifies all members. - - - - - Indicates that the specified method requires dynamic access to code that is not referenced - statically, for example through . - - - This allows tools to understand which methods are unsafe to call when removing unreferenced - code from an application. - - - - - Initializes a new instance of the class - with the specified message. - - - A message that contains information about the usage of unreferenced code. - - - - - Gets a message that contains information about the usage of unreferenced code. - - - - - Gets or sets an optional URL that contains more information about the method, - why it requires unreferenced code, and what options a consumer has to deal with it. - - - - - Suppresses reporting of a specific rule violation, allowing multiple suppressions on a - single code artifact. - - - is different than - in that it doesn't have a - . So it is always preserved in the compiled assembly. - - - - - Initializes a new instance of the - class, specifying the category of the tool and the identifier for an analysis rule. - - The category for the attribute. - The identifier of the analysis rule the attribute applies to. - - - - Gets the category identifying the classification of the attribute. - - - The property describes the tool or tool analysis category - for which a message suppression attribute applies. - - - - - Gets the identifier of the analysis tool rule to be suppressed. - - - Concatenated together, the and - properties form a unique check identifier. - - - - - Gets or sets the scope of the code that is relevant for the attribute. - - - The Scope property is an optional argument that specifies the metadata scope for which - the attribute is relevant. - - - - - Gets or sets a fully qualified path that represents the target of the attribute. - - - The property is an optional argument identifying the analysis target - of the attribute. An example value is "System.IO.Stream.ctor():System.Void". - Because it is fully qualified, it can be long, particularly for targets such as parameters. - The analysis tool user interface should be capable of automatically formatting the parameter. - - - - - Gets or sets an optional argument expanding on exclusion criteria. - - - The property is an optional argument that specifies additional - exclusion where the literal metadata target is not sufficiently precise. For example, - the cannot be applied within a method, - and it may be desirable to suppress a violation against a statement in the method that will - give a rule violation, but not against all statements in the method. - - - - - Gets or sets the justification for suppressing the code analysis message. - - - - diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml.meta deleted file mode 100644 index b16412ad8e6..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/Google.Protobuf.3.21.9/lib/net45/Google.Protobuf.xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 05459738c7bc33eec99c6d6b8f458b13 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0.meta deleted file mode 100644 index aa6506e1e9f..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b4d5a28791112380aa5aea8031f224bf -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT deleted file mode 100644 index fa3121dfaf7..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT +++ /dev/null @@ -1,23 +0,0 @@ -The MIT License (MIT) - -Copyright (c) .NET Foundation and Contributors - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT.meta deleted file mode 100644 index 6cd0abc3d2e..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/LICENSE.TXT.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 32e12c577ab96df98bd62984641357aa -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/System.Buffers.4.4.0.nupkg b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/System.Buffers.4.4.0.nupkg deleted file mode 100644 index c261fa8d8ae569888c40b4255642ef3afd026f58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78363 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�~r(0B?E_LQt6ou#J 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%0DV%GL-7lfv$jZq+l3F9+zd% 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 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll.meta deleted file mode 100644 index fa353346964..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: 942183adc788e0da2ba118ba81be0388 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml deleted file mode 100644 index 8b1b5cf90e7..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - System.Buffers - - - - Provides a resource pool that enables reusing instances of type . - The type of the objects that are in the resource pool. - - - Initializes a new instance of the class. - - - Creates a new instance of the class. - A new instance of the class. - - - Creates a new instance of the class using the specifed configuration. - The maximum length of an array instance that may be stored in the pool. - The maximum number of array instances that may be stored in each bucket in the pool. The pool groups arrays of similar lengths into buckets for faster access. - A new instance of the class with the specified configuration. - - - Retrieves a buffer that is at least the requested length. - The minimum length of the array. - An array of type that is at least minimumLength in length. - - - Returns an array to the pool that was previously obtained using the method on the same instance. - A buffer to return to the pool that was previously obtained using the method. - Indicates whether the contents of the buffer should be cleared before reuse. If bufferLength is set to true, and if the pool will store the buffer to enable subsequent reuse, the method will clear the array of its contents so that a subsequent caller using the method will not see the content of the previous caller. If bufferLength is set to false or if the pool will release the buffer, the array's contents are left unchanged. - - - Gets a shared instance. - A shared instance. - - - \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml.meta deleted file mode 100644 index c7be4ebe834..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/lib/netstandard2.0/System.Buffers.xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: d0a0082994d341b439ee7e8ecb0b087e -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt.meta deleted file mode 100644 index 7bdf2c0295a..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/useSharedDesignerContext.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b810deb288fffe9e7a41ad08ad835c80 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt deleted file mode 100644 index f35e2edd3f3..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt +++ /dev/null @@ -1 +0,0 @@ -8321c729934c0f8be754953439b88e6e1c120c24 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt.meta deleted file mode 100644 index 627b93ea4ac..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Buffers.4.4.0/version.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 011876b4b4422eddcba6bcd873099eca -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3.meta deleted file mode 100644 index 4ddda577cdc..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bbbe1fbd2fc4df71bba55b1c2120d312 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT deleted file mode 100644 index fa3121dfaf7..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT +++ /dev/null @@ -1,23 +0,0 @@ -The MIT License (MIT) - -Copyright (c) .NET Foundation and Contributors - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT.meta deleted file mode 100644 index c4c0e57178d..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/LICENSE.TXT.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 9eaa875f814c8e128ab108799ca8e8b0 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg deleted file mode 100644 index 5fa15502c47f9d14590e3db1ce1b8370b4d1ad95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154054 zcma%i1FR@Pv*xjF+qP}nwsDVb+qQk~v2EM7ZJ)jW+w5-MCYx+0UDN65>dDkpzNz`D zMnM`F1O)&900ICpC_yejFxVIo5CGuwUx)rTtM6!P<3vyQADNOcX*I}zAo?2e6Ew${ ziZkA#bYQYA%5LdvKoo~Fe-=<2d~!=|0YzCdM;Dgi)Rv}czq=iw!(fX2C9xT*9HImP&i(tq;fDngLzvCEkpN*!1tJ&KxWK znNSDYPd2fYRBlGj&mXtF%U7ypWqzxG$-I4EUZB=K9bT8LmAp>qP-}G7g8j((_5vZl87jvjP&E>3?;jgK|9EhLQYUmIAo;&r~8%4xXx;8zJ6m=)w;-75?A|~i22!q9N@q;* zF&d4aC|g-l1}v(K#Y5!Qk)mL#72z|hcZ{f7F(J5G6=BCAAeH~{9K8%GH2acRMce zZ9s{ZS$G6&!Pt**Ui8)pc4_BC-Voq1KNN|>9N7slG%pJqMGrFO`r?6E$C8xH!u;lj zXqAi7SxO4Ak<}R1u~0Sa2K^B9Jk%swhTY^JygXNIowsY%#+8w&P-_q|2ua9zq&&y= zp>_yp6AfL}zy@-l37O?)jK{2VALUK`gPI^?y=5fiETdFgcU4GhgsZl!MyM9v1)7K^ zNs2~BX|*Y2!Z@JO+Xi{Dp(CSiq$11WIKz-n!pxMC3nIHfayTMX5Sv=El`wy2(%F3l z93CFjK6uS|g_sa&5V9towKyF!9V47msznOT)Bu6&sn2g?mrTkr)~3a)0~E(c_^@-( zAc1d)NAsIH%9yGXabsMJ7om1#%76zLdWMMG-nRXkn{_)WAL-5kPnd;mq(0=8<5|=W z{JeeAwrw>`gw=ZCz>EieSQ_5GX3h4Z1<{=wNYwr;*)_%=NG!`WIwmPyDX8=UR63mi zQWslA89axJ)$shG*_;MG5aMcZi**$7uyyI|iWP9%&3c@uaAsq8WOCv8`z5Jn?2luW zWT~7?ObRY31Qku%BQs4aVzHfLCV5P{=I$N+IGll#<>OMIBNB4jdjgqRj|0({v z5zwCi0Is>>u6EwjEZff;if;jP*M#U0^mx?lVtMK98E23!e^bwrH~xS)%fXYN zAF2376e=B#TwR-1rJaMF*Ku*v#SxdDR!@6*VD7B1q%7}CY5i=!>2|Djy-)mij?K_AF|cg`%|o)9@9ALQoHRQ<(ydhl$%gZ;tW zV>xc76Jogc4IVny>lEL7++4Ru-Ocd~DEG74Y;iQXG}-xkS`fMjKfQ2>odOeT><$J) z?8!3xOgG7^(8u(yAwZY`JC9@?a%cPSiY$`-c^L8M7F=BZu|W!l8{gfx@)q#t9@&6% zoH1%<|H=AIlAKW9_$kCl+*6GE2 z^+oN#Lf^NzQ5H7McKEg@k%to+023jH12paJ|72wvVoGb;)G%jN}>KSosCz(aB0wOp6tF;d@lau!qL#Aj_-%VKVn zCNSc9l_5_N!GaO@VHR}PajZft8rrJ@t*MZxf~K|4*q<-uXQVGWjBFsK!jcq|$UP;& zEE=AzfuM1h5qbid6j?8to$EWzSiD!JQPdxF$ei26#m>x1umrV+Dvn+R#mE>QJySqH_vSO3R{no{6=F;!vs!Kkm*=#AIhgyluU5jiM{L;>}+>X`pNLyy__E>!fmdj;W=l2Xla9=;fkl?rNDtvlDu-}?O#55(2k)XlBvX?p8nCM| z6SgHt^bv$(_?N1Fvk(K=&j;EEWxOIL*;5>5J98zESg2lg&hQnwU%i4aRSRKn zCU|HrpOF=`KEueHsjtb`SxuhdmF}1i*DB2Z4CF@ z`uT<~mzCF%yExi5*I-q@g@naH%jY0BmJSQ{^$%{h+lOw{75{Eq%jtX{>FG!5>6-h= z6L+`b>bd>`C)W$O@CE1U41!V^a3I)pDB_7gNI$6Vrrjx&{^qINEar};g58>V0ebvK zX;urjGgpz`W=U3p7xSIXO6U3+{D<7{z%a*4^EQ4%@qWsoYsnyP`^@q3++cMMpEJRy zx!s{|vls7509Q~Jx22GJklw1R2iQlFIT?V@JSq_{9yHaOvz;;3^Jo?wYb zI^$1rwk0OeAtuOzN$!yph`I03T9BQ!)o^^6Z$?1()tp_mzimQj7k!%L*iq;gP~75O zQUQ*qu>GY^c*qxd+m7LjBG@zx;{{$3y77rnnG=7wisuKUPgVYeesJtvnEnM|c1X6b zI)_opBvDAE@$%6oq`7=o zh{(3?u09!dGN`Aa>pU8v8MjsLfhck>;+mu)FS-q1lE&aqxm+JMO|@<$Xz`J&swHMr zHm)$n!w;@!ZV*tCvT6N`Cc-#05Bwcx9coSJONYtM3rv*^3Pww4G?-OGar^a(9m=_O zn%dS^Wf%?h%{B(oCUN7>B?kbYr{Kh4aV8hwEx^1dBgbXv<);5q{TKTuqWQ+JGJM&mfQ&EciV>LU-Je)lMbHW zWd>*EeO0Co>sa?4$Qx6kpwNDf&jE`&diCz$fMTZbuyeG7f)uWU?>px_k;`DRs&0{{2jCh048DbgrU{;`QE9q28sd16 z|JdB!oFduZnND||zYlRAhAj&^P7j21S!4AS>^r%)wvIfR8RO6M!6@y)2)2b%NPWRwGa0G{p&O-^8*~jL>V|IRS`QafUtGD*8qYM5%@~OE z25>EsIfcsqqTR@FAGM2qYC3uabGGH4)Mo{+8?!}U_oTt6Rks{v31!8EdO=z@)(dK8 z0^yp4T;!K=1bb#~n-woEv(vad&C5$_wIl~)kHlr|p1o_*f-ei|MkbjO+*wsfOU zpTE_chQn#6dEtJ;Rj{is6PL*}&uJ1PYrKzR^m8qfO|g)g0x(K!*+5KS9cpl?Q_hW< z?MzYN1ah6TsJ9E?ajciB0ZEJDO8!D@N}z(1$vV6O6_Y~G*+{UZ9ctTh1k7~MVaTs# zaSnNRR{@Vyt`{r`A~QUvV`UE|$ectiQDE+^Z6ZnKXk;B z&)K-a3x4+mkBzWY9f>z87Ix1#YN+-IpMYHo4(6(w33EuA7<1Xa&TwTT6tK&ugF-K2 zwyRc-V&`}Xn{!}oICEk+^GZs(w|q7()_3ExCz2(m)>%m=;lDq=L+l5`o<4=OT*lgQ z_~IBpv}Okbw%QcgtIP15P1+ci1W+4#`>|+;(Zj14b2J z$9Zk`P#@+*7$ecL>#Qa|lYpZXeKrn8X07}IoMpTrGP~5tIP-=u{*7+5$Ff?wG`P=4YBNO^*e|tMEJM@3hD*a_% zxMwv{U;8v->zN)7NSY-)oGm&Cr<4D4f6C}Ey@p?OKu>faP+0abJbS#K6}7ezMP?3` z;Mz};diq!6A(HgJgjb!(SgVc1ZbL34QplC>VW(NWP<-TxU z1*Y7AM?&|arFP>i#Vdaw^s@7W*WML&$BViWgU2S*Do?89N5H=jDX1z5TESXhma3oxN6-$tuzgx6$%3xm#6=apOEynKY!A zMe`j|$3R|XjVI-?7&g;J76R*0Yy(7ElYi`Qe8_AeRmMs{S1nBuuJLx$US#q|y1EP6 zp|a9tIMQ||o=|f#REpSV6IQF ze>ZPFweUJRP#dgkt&+FjTC+|m>^*HxnJY2cU2+0Tco?Ts!9dyp2vx|Rfrm|pWyr@` zhyl`oG`9!c2!p?52XxYHF+pGek-Mns8MVtH?V0wf+SdutajitEM1>t(ftR(C9)3a- zKnZ~Dn9e8mTf9l_XWAtKu5h2%hhIzaXZjh!CK({!%)oTtli=5#7SCxM?A;=QavzKv zl*Q~J4YE0=?qKr#GEHbtLNWL$sxsj6;r8?QwChqK2fWAW;LxE{F3$)tHyX}pMn+cB zBzq|jBiQ;-xsxI$-c!lnH5g@T3 zY_hVQ8v)BRi}#IkXjj}wdk=$OH+hj)9!&6%j9NSF^{Ch$GYNTAJT6l7%&r|FbW@XO zq`9h-R6~)X0!xDKub~snYAsY=nb(@%eSr<=Uq=mxW}wK^Lp`QWlKkn4X|quh^4PG+ znp)4|KZ_;tLg??)b3FUu2c~)wcX#iGQ|zU&N<);j_3_@n>B4&OSoGmDe-FT?SCh9}c{UztAfD=;8AOR>hAx9NZ5KqVu>RYf04 zQuAi-6W;Eqv`n8_*nGB$ebV|JrBRZ-v)zLbK@gB6o(t%q4Av zkU#zgv#^4oRdVzxbKWGk8cnmd+Z?JGUo@<{j!{q+8iu0E>o5=PR%HMC+Q58UJk8uy zQ84XVD=)t}e~k{LVml6qr0UMkhiYoS=2uhjIm%Y7Dr3W*r7T|{eqNHT;?Y$o`F>XM zf&2~uRo$p4gL3>?38c#Kv}(Kur!EJJtiMgOygx@4u%f@~MMc}mFl-GO?lMXO|6yOm zX9M^`y!-tn{^~9KrT+LQdhtG_g)aR7|2rR0n~{`9{f`Hr`q%$MXStd>I$7G=(K)+2 zgZB3$0wBPE^z~wP2O}5YaMu1JT{$Y%*BJ9;jUChNI3p+13gUu!y3^wSuRQ_&D~0iI zoB!Q#{*7FmOqDGR9ZgL{Or0#v?Mxko?d_aR-JSn)k^i?Q>OV~zOCx$aQ)gp)M^nQ; zf0*bP>GkRK|Ch@D%$FEug2sdW$RvX*=T%Yd-UGy0?{s#Hs4ILL_B;o~{w{N6V~iQ#RVYRFuEa^Jk^=k_XTgP+O=Y~}_bkR)waT(k z#qXy^v4mi3;0kN)X})W0BGhfm2xs;VB_mX$W%^-5rF$Q-D)YI~!t#54)v_0!N0rlB zoB9G__^ja&V#8<`V-QTibebsDt)|J7O5h{xJcN3VFc9W2{DDQFBub&j zJ`0TC1H=g#*2Kg`V*c??u!b*Gan;`em)K5zU!-jo5f6aWc%|5%V`^I8?KXc@+Ui-i zS|I*r8wx$CV!&x=UaY<@gyN2Ic*>WtS4!v=_zoM_c!_ln?L*)i1VT#4m_4u_+G(h! zSV|NOoqu%9;D@6I9gUKK&SkL9+&2B#%Osj`zOM=R39;TV$ztJf!AOayv3RA2ZX|=2 zYsG+wnt>=%{^lzI+m7jj5!aoobqGc^GNT^m?C->&3O-DbiHV{`2C?w%xwl-wel@-= zM!NsI@ag?oTAI`;qt&v5U$bZ(T{-BOw!j7}TeU^qly4_&JZ@*5)}W82&_LZOakFhF zijiqz-2oXXM!i+QG&G%NA9pb$wsGRJlC)M#3nkfZ>bcPXAa@o=i^u+ZanY8+EiIgk zYFv~crC5x?#8~=E>dI#uHYX)uBuRrCNH#e1UG@g|Bf}96*|~{7DG#3C2igopZ>SJ0rgblP-CA?BzNuMReaH6@=*~6d|9e8nEtDe(^9wV$*ocQiz(q>fin}h zS`W1wc@uD2I>A%3*|y*jlG*GR9|EzOs{kBg^{MH0(?r3;Hvw4wxi!CzFq{jXu(p7j z<_5<#7o}E}LkQeaM6Puuz9;va-chAT4Kuw7&xR5;x;orQ*IbF(9KJ`!CVpgZVG1|C z5LU#)O3%cD_gPX>v$2CVl1;)*4Y9%V(@a-v-`JeE+{Ib0^W&x-x%J9L12Epe=B6+Y zg8ePzl#WyBA;u&u&M9>8W8l*un9s^b!s(H}rvSNp><4kb`{CJ1k{UC~ z-WcaBGGN>GTh|H?rX}*uIT1|wtsNF+DCd?fBuWkbG4PY+(Z&p!_n);w`)5)a+SCJ8GHkoE-CZMj?_dl@3 zoBnM}(dlXZNiInTQXHK-)f5Qv+f5Xev-utlzK31as@cCu-~Sh{ABG!x26qbpz`z9b z|A!+cHa1J$kl8ru4h%bsZm&~UHnUeRQ!{wHiKOkkyv$zFYFfB0HtVVJ@aw5+FH;vy zaGP4yy4u!tV*~J|62&wBqPct+;u;?{6`qP+@l2Sy{bBf9@pq-*TKnikw0wYu7b7*!eKyr~A;iT%4)70y2%6V{lPV%WAy9;4T$j|19iat} zD02`Xef0zpC0`z(6H)zG^8|r^*MN4cLPXyrBT2oP%3yRtpb|nsx_k40olDP2-l;=~ zl=0&p%t8)RyWzBd!lAs5GOE$hRILde2pqo++zTU+t=C;q@%SM{?dih&QjNxKalwZ} z28_!z`R)X^wrftEN<~vnkU>S>)e6bHE!sl|_Ai$G5|e#FxZ4Fk?Dhs5#f9Hc2{J^X zM=Vh8(M3H_R+k)vyAzG%q4>q~l77^bYF3K$-n>in(LrS}Dq?_S0yGt;+;a=U)F&_O zgvu+c=)yJuy1zC|QBOWlZ7QGWj!lPmHe(R@i#P~$xp_%(SPQ3wKcWMS2q9)1ZIh54 zqw_=qnn4w5Z&eW#o!JHKh9C_#G87!>;R2aztT07AH)@0+PqY|vPB4HooWD85zq7fK z&pE;IHo-!Tuf;HC3l6P&ci}tK!uE$@ra7QFr7Nrw41fUB8s}dM=Raats6#X*3XBpS zv*}kpVp=ePbod9*i7KQ7@Q6i;XiW>4f@Q*4nk7qeM${Kt$am)3EYsN`&b|cofR_L? zNF|$~qwH@-x%kko=Nm+r+6G@#Q>3|!8VD-Zt{r?~5l}APa+I1-n)=cXO*icc0kf7Y zcNjN-kk8~!ijL=qB;cV0=mpLv4ZXYg_lQk0k!11aU#uuCN4#8FC~KL?APF3w(bGE2 zP~s%lW^)@zSqZ)!V6#o#aI#Gcf5xKX*AFLw&w~h(sPcHUA@Ur7N8K7Aj&B3hFAxk) zG-xE6n%Ar5(=5Sj0Do{wcP*%tXz47Kvbxk1N}8t_p(#LsU*Kyo?rr6ks2%8q>#YC1 z&_fZy=png!u*??w~0RM4b^~Kb!Ou%j#LDxjR+;o^*ZEEcxixpD_I;{)8 z+|&Fuo2ilmSvYevv>dJ)XZ_+1)wj+iuc7|V=)V9vH&L^`k%7C@=FSwRcN%G9%SF4E zd=z~Pz2RX*)<^}%fk|kglbF>rbSanlWm_MTW3VSDE5#kiD zCM$LNUi$*pS)P*Qxeh~M5XEkikV?}P=#rzR#jzQeO3WYXpFV?r%lIkhgk&@4fkTa2gvF<6_xUxOlp3KiRl=vYAQ|l3nDU5WX9K5{Rud7A+RnBO+vg*4$Uvs0=>^} zfHD7M11rTvw;{UyzO&|`(228MYU15MGZXIx*~U970sVmpRSJ3!qE^!hNrYs9{FUMM z3DNcnen$??CxX~RukdSC0)nm+VJ>A-<^Z`tenhnRClq-HYZ(;2#EgZz$m_JkSOJh4 z*@PkWB>gj+kwF;ddfWmnJbRw@PXzL=32Do$lnfvOhr$m4wco;I*f<6sD#Vo}*6}Up zAlI2{gUNC?21!LyJ<~Z;WR7BYL6cF1f+%JR1OQ_=gORqIK~444*vr{2k($9e(7G|& zbkc;4w1rVTJ1tjQyLzB)mKG!ZjHDB@XlUp3YrWk59V4XQ*5sUnVsZ$f2C}dv2K%yU z7p{LV)AE&|a_Zl)l`_>cvnxeO9wn4|TZ#dF!IB~1U;mpqnKevd=f6XNfuy9oi(@NE zseq)c3x%fnhs9!F#KcQmkzme(a~9LlMjBGQ721)|IVD`?STAoar9+E8`O?zkEBdE8 z-W_>i`igFB*Zkfz#+9QqNl-vij9XFlv79xT;~Uka*w3C~pu={AMRiRBfEKODMX6SC z<1f|bcMHE)Ju=yth83fc;8dLP5oL$+`pV99vCOIX;J~&%Zdplqn z0Clyo0L~;JUzk9T08?T9c|rzo{_O~Nz92#+`EDSMve)84w6;ba07c%SWCennWG2-6 zlxhbOEoxEBCFc;Ka1zc+taJKg6I<&kRDY$qM|4 zQWa_wD3a-C4w2Riyl~teBJ6HShTwdeI&zV~LH2K1> zMsYD#Gsvpax@w0K)+txj=eA&H=|;j9Qp>R%_gXEX&32yX40(JB5LPo!AI+NP&w|Sl z_EP$1>BElKq23^3-lHc2UaL!_Qp@b?n$4UA^@XnAJ^WWwCqd!6bVx*kk@bbuS;{ef-w07w7a6}-^N1V$c(hfH4h=Hi9btfjBP$Nr3mr?qp zbJ;^$Z7`!2m5p9_O}4d4Ima}8OvBf~>;OB#9!PfwsaAE)55saU2c3d&&u=_15}HNs z7U;0qfIPh^CEW;%a*5EPlra%Y-z?_zd2vNRX82}##7K!Bd5}-+Z2u6CrU%N^ z14t4rpLV;ow~Z60adt$5Pt_eEm*KrJck0d4qan5>q~Idt05bW0=Ca-}{n&Rtgv@AU zvA&V5DMrvtzS2EV3Zam{7aBSC7jwI6N-@r~ojA<&Z(}>Uv@s3_zZ)22)AH#@9p53T{9r|w8(p2DGj8&2es7XYLd%^MJK@yP;Vxez$&RKL zo%9t$z~m!DZ#IWGO*$|yQ+&-6f242@@?fz$Ml`-WQpBNK0ELGx&DPV0QlbsFuBCl+ zKGbW8CR(#Uf>yxhpflZ5eC}k#oi8`Lru8IjUS(V5dLF+&9ZRC!jcK1GSuSPEBlEZj z=9Jy!4Aw$onc^2;;-=)`e)7qrO{Tn875005o=bo`O5)Wy^)vkQ zJ^gCjWbUICw5C@;IuY-s6Yp+xR4xAxdZr>4who1QH>rB!@xUk>|0=>em{gj#27K(G zf;f1`xDw3dfTL6!43>l&`+^kfnRxuylitXs8-?4hz3R7(t@jp(MB2HvjN4P0{!N^3%Ap5mrN z$djwvYDAKPxo=#$vmQ?+sYK@{UBG=E?n6c3B zd2&WYXTyKDvws&ZBTvtD)YneUg%5@3#Cd2LIbp~~OPj`yG>R&Ww^GWrwsEb9Bg7KV z5G4s#4Oq}8^IhVPZ_Ej#FIp2xmu1l;)4?(?%v)ZGB&e|Cae+y7 zDj-?$TK!M_M>V>CfuP;x+HXK!dI51qKQ_h`2X;^90vN`fN}{)`;PVNg18{4W2!QMulrz{psTJP z`}9y))X#h?55oz%fpyEprIX4(0JK3cZnl_LCJW7-w>-TBpB;0}Z7#E&?kLQ7hh=|m zoOH1zJCS4~b78?S4D*xJF*`JT+HDbYQy;DXUp!0gq)on8!nvd8BOUi!<WP{rN$+FTJ3NqANaOWaaq$tvuSj5zvEl{(RmZ)u1uv8;f|cIWkpP)lbJPRo@{{(n@nAoD+AO{QsP{XyX}HH6 z=$%eBvE?t;?)a~MY(IIf*hPt&UAt23}mx)kUI~u zXczv2U9!(<3@(S0#i5r%{!^4F*TCdck!Ul{lQ&5gtp(%_vtr0=SxhXV0Nl$7mP^TQ z#0LeJlu!Wu+mmqZu#+p_QrcAVM#7be?sL8KPrT293Lg)@wnef%Cw1O*)H7JWzIYzY zUE#6TPK%C`LNt4@yDf}GQ?l{9(Xl__95zVL4jfqMDMroVE?V%W3~K>D?y6MB$qyjG z(g79f`w=!_VY~4fd0bI|%2ph3&Zi>su=tuC-!*j9zuE{Ci>x16pxshGW+tx925q^s z>(>5=z$pp}nqL_&hUl9giL)+;Z!|Tr7WwY%Tjk9kK2{}*D`j>g+0Ug@m-RBS1fkC* zKbkwA3)FodD^4hT$2!@|6Df^1Ws%``%9RwnjW|8Y$6|goqR)B1lgl3H8E)_FyIj`A@jnve zhPuwXjc}UkWxUoT%MIqT?^s?d_GnyJn&26E4{|b?BQNDgWaf@pXZZYO+ zU8IaVR~RafwU-@QRJY6K)m(&@gt6C~^#39K8TxD0IM?|2!!38NB9;4aqeD+ZBySZ@xf3` zc~Re_2x4Tfd3A8q^TTdnJsMND<7*50+6Z;w0z==5R=+aIcLjPF-F5p3%B5${RJ%KE`fvWyy{Pm4l1?Bbv5o@amIvuy(}ifshGL}0g8N<*`cPfD8WvS@DixDi2G16 z6)lWHNI>Jm9A!ds)Ujj)jJwvJIEhDCy4M75;_a0n)Mum1d;6Cv36Ci15AkBrlp3ORLH?|Ak$Kdy0Hnq`@r3JA$2nvJ+hDBr-!%))}4%49nwHe*U(lHy+cmRb6VcaW{%5!|RwvK;w&Waq{L^>82N6 z`a>Vu0**$cGgm$-mKFpgWgoR&n&pv-yJrxK6%B=Q7ut>RIgCPU(lQZ3OQ(yP@ljhYW&h5!1&vtF+FzUTywC&$i>oHm-?ipxL z>;=FqO)8LQsa7oNGN-rfSXPb$f0$h?k$ITwp*807cgZB@C=GFjjPwwq7^7VXtkDMJ zusWtiU157s_^^t;TErVnQIA(Dh8api7e$Z#-oBu(w8Q8+8&m-M10sx!l~K%VBbpJ= zOxVCN!N&T9>Yfeb>$%Io8ln==XyPRE6BK)gg~w2gUkMHoo7SCF#? z{{pauD8}?kCP2Gcp8zw#E)0eZ7z`_LC^3L(aj3Lp<>TddR_wqVN>J}Qf5)#T0(|f! zg`OWXX}&NHxvzlFNx%tTBi2)f3O*8Vq3+2jw_8S>V%mH9uBmUfO9no?O9r^6OMRvh zrqFkgkTqk9oXR%vcsN`4tHxjfRFzcX~|ZUDgn--?ngH>NGi8FksHr!&5S?5f0c@#dOFx_OvH z)SY=$kt$ndd#@gom!&G2-k>7gC6?Kv?hRI#-zaqlZ0u*0K-j< zU_$}($r=P3X2=ho&L$M!Cil3K@K?V9mIo{9sJG{(-Lt0xAZ1W?LEV)-La%~#Tz7p~ zG}bG~vn4|hzifoGu9xrK?OQZvKs<_%9B)$82slB54+%SZD3qvv|BuYwt52Fqkui~$ zxxPUTXo9!*8WX8BCDvKrr9p1qIlY*z$c+s#me)v@^?8eiwXL1K@?{CzieXEAAwFcy z%1hgvRf_$;KT8H{7DR1CCc#0&Rermt!5TW(gW15mD+hPpdtxls{qaVnzu-5Av^<3h#2ulUZR$3p1G7jpnVB>uLSKa=!Dij|d9gg(rf9xnc)nSabFC%);>-B+ z7QnR@Zcolz6+L@MzsYiY;ugTQ7s@<7RFnCZ5_>Yr{+2!Mr#>;}#;%f{O(l`Q>`M81 zzie>^X^)%wLA)3rZJwW@0u|jO71YF1krUKEbg^wzOc_tuV0Wv)8BXxk#s{|!jJ53R zU~XY^~UMTet7${)D@Vj8>m_F=I)(z^4< zGIseLx$ly71)z2Pb?lmT=#od$>jAw5#<`v4+}VV%uLHe>=h&&@+?j;1F9*E^jCF$_ z?aa9g)xNVkasTApfvt`q(n8YVV4rUdig>_SJ43gOO|Y*zjf0Hd`2-QW%@OkA{RJHL zVjcC$nA4kuXXu)c6sX)<78^|2WO#2+_eNf|UU;P8+?4Bz3>xzgxj7YjF98YqG4h+= zJ24Z1*$BsILS(ccHkuO~%8v;b#6}FVdr6Tp*FS&tzUGOdVETK9kIS>j-gfFy7-a6n zE&n?Rm&W>OP)+wZ=Dla(Hnd0s?c^)(DJ3uVP3ne(n`<&(+wPF)q)oaj zqI1T_$SaL`_Vm%7ExkZAN1{>IUFr=OIsUw6@*V`r4RZEe+|OPpgTimUAk80YWE zeQiv$o2+PTYxdzWBz-jDpJ;uj(`RPK@avr8Q=%EBvyIKpC7LYIxV=L?%K? zJsG3ngGZCp1gX){=PqaK*zxMv`8OJ+L(#|7$1a{twO1Iez<^8e zpDtzCQ+Fk$3md(^!rB^9zG4+w3aOKIG`&`IQT)gdt8#X)tE)E;rG2(~u}pT5B=%qo z_fZ{rF|fjz6%_FTRlnK&4~Jo#a${txdf5A|%^CPWm87}EfL4YPIObWOF#@zde>keg zn&lgq)f*LlD66%#My1alR-Kp`CTYjtJ^z;5CsEDLJF&X!l%Fzy3Ke|-z|$^1Vn~g> z&y#oKaZWm|#S;^58uN$5f(Z5dHRo>fUbZGAA@&Th7Jzvt*zqDVbWj=a4Ht9bzaI^H zJNd&gq&%`>(Em)Wd@0aDz%B(c8(apu0BJ!DHU}2OUTO+^^Fr@lS!>Q>8C8M#T(2~m z?5iczpgQU^xbUqN@c=E98O@R8Eowv#?!NbeWk2hKqsScRR?*Icamdv|&)_>`2hefQ zA9B3Yakx2V_tSBFa?U8AXWQbKw?WIH{!wA;VLwiYG0*>-_?R_^nULVDh6R_4ro8bO zBATL>t1n`F%&Vhbdg_{7nth)`jY+k3%Ki~WbxXe_5mzkcNy557T#FQ&zoM6j-@uK4Zun&CO|)0pD+^BXND>ll}$0)!gE0B!LlPI$D4V;za|5sxpXdBj>QPlEGuv@QtUJij`u26atB; z0Q7=U<<`2?>46%TsU_oesn+?Im`%asp(yrbnilqCnD%*>tWNcJS6j*qZjG}Y3c9sY zTFU~abqO;K-O9vFGaE)%d0WIxE4r;azIDlCS&g&aov^ zZ3*9sln+Nsy6U&OHSjliLC6d{x@{xAWy#}<8rNSmwED`2ZQ1FEREiMC7_Ar5ZLOA7 z5u>^Yk!&r`IG+1?(JarpSM2Rm?SM~jK)(nu>+2V&UeqhpmE3WT_-jnfeu(&6%n)(E z>zC*svXL1aImv>6JRG)pH0|K00=RSfz4IX41^Bxs@35yB9-n++&)Bk4uHxUsnEWG~ zuqSd4&(EdaA;Yb)5&e3>ZEWG7j#!{>jWa5R_foorWcphQDa-cO$WSv}#tDw9H#t8= zI-qx=JNm$AQ3V^sWc^?$s)>Ib3US+CSOalo4u6IGSW?CFli;1j3zT03-u#7W;GONv za|qLm6JPdbGb+VWyB>YpX^~ABsn*!j$(q{RqU4G!KTlcfQg8}o_S3db)!~(jYn)DBqI)RYH_TCDBEBI2L{3HhMiO zYW=@kGV#l0-C%mbvc&Szw7Ej%GJi(lH-Bc(hetlYu(#*+?H|;~?i|G@x;I6w_`aCv zpq_Ugq~=v>HO+Go4$g%xa?=FVdY!eP+$SZd*z}z1kVo+3i{3G1wB4SB^kMin(zV?N z6vBu4x6nwNUG8kq@QJR<_HyXVYV+I1;04&vphbdpFLji;JaiRmwiruFJWUV01UiVd z-O(*WnikqgfBNG#QR1m~kK}nL4w=nf4n9tn>?yGveSBy+!oJuj@{?WY zkmnl0nF8CvOZJ}^cJ2v+EW#T(Xcn6X;-1c^r(Qbu19h4i)(jhAedBRbdz_kf2g<2) z*FobU9F_#%E5#yClEpkY-ABRby)$&)QV>sGRWLMQF6T~L?2t(}H+lYU70U$}>s9j? z4L*rF^+sg&AUSGCk(74sBHcj)rt+y9(+|~rYs{y0iLR(5Szrz_O(^k8q%#s0_hAf2 zt!K35NXpO(4>ljjtbVPx#eyo)G@g)u^p`$u$v_OovFyVHJAiE*9u0E5ziyl@N}X78in1jkM-F*#5(Dov792M2~N_Xc3MA$(2$#Nea;$SYv0qeNzaGj>06 zM~N5_7^S9|A7Fod!>5NGe)piYmRhM9t!AYYZRUD+h-pWQj`!x1%pkGw6Z(B@zG2`* zLDGY0q0fJ&`$6Zw_ac8)8Bl!S2I%YW|L}4FHIr0y1Ic?)MSj4)JvRAcH-g&!;8*m| z`k_B+e|){xY5orYTR^10lw*QglC#ODY;Ar76TbD7sg+c1ei$O(v5N-!f>0FSOVMtZ{;Bn^(KYjd?k!1QZ;PW&r= zM*j2<$S*tKmob-n75tp-UyEJA*&%!|cdSZ0_CusU0a`788DUcqSScWLHIbQOWTqly z)^*6TowBTBS=NQJjD)bWKK3>6W6$pLdq>|aSE^Dzgl_xj*CP6~-wkmc+!14E0+IQArn_WjTA?cta4TEy6pn+CUz7;gs3L0t!4L5@{lb3g8T%rQ5-*N8TInKa` zm9{^d;seWEl)Sq%@{p0ic(x=|MI*KNL2m4ov`8HiGxD<{zG)~@kHne)gRByzr%&x? z-;i6V;ww@U;t7m1-!j4?#jp5%T|WcNN$fGRu$sNbg|TA{cx;9d8euPU6!Qx|Vx$&+ zjL*&Di5r72VA*G-;%SjX=v8?MKZ>PL>VZ=TE>>8w(|h<#@n8d2IJaMNdJl4>+0(bs z*XpcQ?lyem`kzp-_am%m+Ta`6og^^MvHDDRGk%C}{{KbWd`epNlpvK7U`%w+Pf3)D zYB5G1GZclMUO|F!QS1#;X_3xO>%#Nm4e^Fz}tZ6#U8QvIKvqr6#tzd z@hvN}(pw0>C}ufO;x7aJfaMsb90QRYD|51+D;MNinU(zuBK$iZ@Q+bhMpW`GR8|fs zKBa*OrIk5_Q_G(|imIA8{xYD@=UzsJaQy4x$VxF3xi1{~NI3G%a72 z{Z{}zfYEHRLOI=^2lWE2Ot_5hb;1uaxxYY;nmt-o@6aGaTAKeQn%WjAEzvD;@W5N* zG}Z!Y`og~qX+XrIosxvtuCW(Wapoeb@PP{+7n~ zrBvgtFnSG_hDJ~+{|Ny93O*5EpZ46HLgRf{|3jT!h|F>-bK?fTz!9oDM2ZG;+2YT; z%kdil-|F+_n8tY-4F%m@D9uk7;r|=rPouG>to%E4;PUX>qLx_hr#pezl{)weGz`TC z)nYovMAzu<$>1&QQK9uM>`7gwm#%|rdHDBa7S0Ndcdzl2t^L?`+RE);wTt3^3twA5 zhq3FKCWIIasTN|f;LemqY26*61vB-4mPE8$gmtMlbopEIy1N4}()FIOt~KP9r-og8htyxSvW0Wt^XO&i-L>AB*CSEl z8W_uG8tTEpeFD7b=}Xuk7EOY=VA2U-ZA%dvze!Hy){!9j(QwSEJXJ@gI zM*BG~u=~QK(j`jiB1x(ANb?0qR_J%EB+W15rCAP7dF`MQ0rbdg4N0jcdt`Z3#}U9m zP$FGNi9^r`Yxge$5b=LpDr-)Hy~r%t?t7vcB-yhA6W0k{*ekla-mXeGN0lcRqqlomr zf0GOd0}Q;vq(zpt@7X^`dI;}_dK=zqmsZmn%7@coT0&GsT&iY{lsdyF zb2;0OpS5Q8!oo$o?+ssyxeoPU&rT?^Jv*vO_?9})TBOwoMsanH zzT;|XmeK%P@?6cmph4Nvq?)Ds_b2$ZXr@iS7D1V_(wJu%O;x0+5~T1N%0PD%hcc6L zL<4n7mYGSU6F!*f3|~pz$?i};kNfK1K~dFaMWI#um1oIneNNu^0nikOO#K;zwW!um zOPbM8kWN}_(imt#!~0^xnv1Z~2cROWDV9sh;m6zQH9LymZoLVzER0d#_e#0ztt6E5p?!^8Nk+tl zan>tKtQ*C(C9^n(rB(3mYE?{eKPnAV@%-@^euMaW+Simpgen$XDQS}S0D4=M&4*Wm zt>1vUBfXmnbH!@ekl8(*IMZ2;E-Pf$3CZ`pA-mVgM^$FEilyk4jg~^jgEkDt2t9|Y zSgK8SLj1uyGYizxn&D1D=mF$6^)`XN72HU}4*|Ptf^=L+SM>@bsb#AnFbW2WTX|16jX$Ot}$g4 zjS^DBN&*CmU^a9DbWkT7B6lg% zBhD-;Au}JT8vP7EG)xZ@EYea3+KFO%-UbP}EsGe?(+^1+gTHQuUi+Ns&VoMdfHfPbPn` zyHT!?`;UiAzg<_rh9h7#)n3pTbN*YXT*Z(Z*T88jOihs<5gl&C*@s;^A0J~g+0(E) zF5pN=z(A-(NGPa>>Y&^Ma>;r%At{r(q^^|}ZOv{*Jj7Q5=>W3NRNoU zHVp%uNa@xDA_r@tSU=I)k?T-DJ<51Ol6!*sRDC;O^##N99;`ps0~KGC3pFaoIW!Y$ zR}ifo!8`vk!Y>yV*j>W@8WU4FtJM%8w(fm^8LZ4xN19R>*2RK33V!o=?{8HHl~sOQ zFan>+lr~!f%O{1-*60@ZS!Ua~H@C0Z&y;lLoJ%Rb4%c^G4}JSUVg_}c91?9>3CX~c zd*qO~(^ovIlEJtQ zRN`zw5lUni+scm-`HK2Hdx6KSldMaXI^b z^8q$5$Jbr=Q&~fIUU{c31auq6CKq8x=i%*mo2Z+^uU|ssVr-EAq&|$UGHxe0Vn*@o zw8Ai<-COEgF&#hY4N%JRk78Oo+rJU#QJUsnf}<<#)aDqQ8~e`-`SVhIE*GU!mvX>m zKHxGAxZDR^&H*oC`$Z>SjL$9XS-_K|)WZ~aFpRRvQf#`P_q`0GV#>~;aRomwrb^No z=wb6Tg*|f$vxxF3qB$WF^1^3>JNrZddK~;7mH(}TGJSMt6{m zn=x3UdqruDIU&5^7rT9=zJ;)6Yp~atyClTy!Mc)+X zk>`+35U-SG&-o{Dx37=#iuTh)(bqjV4))Du(Z9i*F6&*`#x0%&=u<*hP$=+GxO#PE zELgqbzGqStgd^0>algQnX!$pl;|26pFXAg~(W%fPF|?GMy1{1YKmIwMp%?|D`nNM92n?UVEAyqwX=)yEDth&a86 z&g{^Fd(bRn1mbwpB@kT(xhD2NmTY}&v?&X})snQT^Qx?lfr6*Oy+HTq!^kQ2$otEE zep&H?C^aI4BLd8JNcNfgV78Bb?)5$v0f65&rKI|HuDd@(yU{eLRsv{vH$S+WJbo#NITfh%iLZbU$<;5uU%-Rw zrQhvD;Ep_DJ z0pC^+m=YM^A#TACP8@PJ?dNtZsY8tz7;_NL$eIpB3_NXP$xiOz0iWNMLA!|ZTRNKt zWgIVG$j8h6U8o`uLt18oRz5_EG8gdpq@VkX1$=M(VRV2ipZq)y2rj|%9q1OFiyz)b z;Lio%hv<0G>8o(){wRiV+=k!%n5FiGgCbLfVJr=V%A#bd{LJQv5PZ8nh2O4UkKOy& z4*#R|XiO77%t?oF>t4N9DlFW3;}-XYfZ*jZOEE|rq_mqT zEfvc%gE_K89`rvhDdU&8RBm@D*F2u7MNeg>Byvx2czy=A1>(+D90Od9YbKg=&16Dz zwpO45uc?&0Yc*#_Mbn&HE0%W|AZ?G)mnqN1=re_WR1jJ8ni!pGxtc-G#u`u+;{S#5 zh+KPG^ra$yP(!5(p-RD9uOfdadnN8wM4z+h^AxE>KCd7a=7jA4_sed>c9$_F!f~&~ ziJy!nn-WETw=c)0pDKc^)UplGbC=E=ub0lX^o**He;3Nn!DiO8CW$3vr{sy#WDzP8kPr zH3%PZ>oGb6A~_zyW{5`4C!Y<-$K2hN)bA(tF;~3QUcrMNp@3RN?`FkX&@jN<2L7P#W2_C z)fgV~4M=u|r?bWG`hCa$FZzAg|Hb;fIi%lXA^qOb(61ukoiE3!FJQfr0bRo55a^Y7 ze+7NR<@L*yQ3PRZ}6BG%Vm_bY{@5b zv`b8@25K5QC76^+*kz?vpN!g#%uq&4tCp7K1fc)4G_HsaIyVf$GvMdPZ;a%qKn~4&PKc^*>E&TB)kN3Ab>EDp zO#IL*M9Ax$JgNxSZ_#PhmsbzF;TSLgW6)!tpbLk+Pj!|8i_&(NmM6@`GX6acvkflt#x1oFRPQslX zbdQ^NYC_e|%1NWtr;|zAWBp(~>X8~mJkzg|KChfzA%l)C}~jIL9U z(5u1iX!Ey6tvJwblHM}0eJcpyvaZaS<-f!ARH$Gg~^$>rE$~97AxW$w!J*|{9D9XwitmBD}bB}L)M71{c}N#HC)O(A@(=0_<4#a{du^| z+p!1;8Jg6~{@ANFc^=HmCsQi4ff<~kk59dh#$VejyCJo5&(w=4dNa=74_DSg2-?c? zRA;WTL3Qq~Z1HA+*k93tL#SY+}VuOpayP z5sldiQ#=Z3{gk#$Saakv=f3cU4Pz@H{KYqH!1zQC*iI0I<%D$vLRkv=@bdzA4nzAu ziq(`bBJ#D4{-Ca8e0PhTeX&P3P*L1pQw4DsGr?R;u;f|Zfh$zgA~+YdF;mSFSx4mK z$KX5-XowU2_h&}*Ujm}bLb4u)=RLH3jp~@)easY93eL>ckHuAz96YN5BaY6Tpii6z zL9%*iqMeFCM-J{PR3PMs26=CT-yWac>bS|diXHN9cYfzEL8V=Kw`ze8=vkW}|(!1ZFZwvUo% zqk$;ev|QGXe_s}E^OWP7BHWgM3A^NP%pG-7`}wd~%pdL*Xm5@aS^F*D9y)~V3e~EJnD|IXZV|w6J)%DWIFb?l==S0C!N-rgb z^|a{z3Q*}5+LETBJFdm;S(w1hW>mwTT>}%7jk9T$2oh9-|GEXCH9au9hcum~X*SJp zEsavNV@@t@(k5EQ$iXbugeDIz_~t6iPqXz*9JeoF{$&~E9u#Rn%hlppn2+^Z1~b}( zh7+-xuL>x;j5lF%3)c8l6Kc!OBpWz5UrXZjtg&#Bu*a(wnsw4jG)x#{fE7i@I+30A zo(NWDnUp0S$r5kL;;e_M_%Vd#!kD?Xh-!O8ya4!uChW=%o%qWU{xYQdzS%#6JN)oo z+H(JLu;q>m**^5^0Th>CodgGeH2}Xe41OX2zl$9ab;jzB!Oq~$v2B00zyHMm@zZQi zUlhjqUBpT$t$>{;73bE94zB%H{yH}voyl*~@ESzHW|L=V3CTv}j_UO(AFvX7? zuWn2UIUd=CDSqV6>hhE@z$2GqiXS;r)#d!Ol!Yk)XFj+IxAz+SwuG7ARK2ai?~*X{ z8&NEu-&JAex1v}+znx*`3n*4TELJ`w*5I^c@1X5Rcn0@IU~@i+N9SO$l2O)u7**+P z-GIksranlKYbrGb6l0=hFPOr!x}u$idRUE{rFgV^6V#1el+tV~@d1p&Skoz_V{MRP z5u~(;ubNg7DZ!Dbff?BfG~nup1fJrkkM9j(bbAm@Vl+%mO3Sia!9E=f;8^2*ZQRE^ z#mi_ar71L&jo#&0v}IT{4U3lWR*N_yT1|rkrw{}s8A?|5hYV#3(89CNX^y>Ltq2$4 zVNZ6Rk4}Z=M-!;+v;7xQ;ql!{1)N%iiW^Qz2~LLBRH4$G(#KNbn&VY0%_+Aa^z*D^ z^^68lyAjm^-xS*lLhXRaRRcWAbJ_WKh@OqsFi^l&I5XkbmdtdImyx~kE=_%O{HM@w#ptvH!!a1bFMCE$Hk_`ciycs$$b zS!4Euus4LGkXnVIYZx+H=X2LTev-BIp`PT!r#b(@Pd$E92`w?|LNbO6!D2> z#3#lZzK;2lfyG@(Gx-i~#B4ama-~(I!H5GHYVSWv!lK) zYuQ9U+m61C^l`%}G&ZTUqu$xzH0Hx?=8gqkHm&6N*e@=;41C-RLq2YJGy!O>gFfj-9PnoS6AFQI z!_g|YC0rVCatC1`h9}&O5%@6=;P!T*bjOW5Cxjt;Ez;dN1e2d-XHu>ANiqvsv^6kiZZ;<>?2RpPoBo6zM;2Mm4zL5HtM)@ z=(2%Nu7yt)O(Dm6g-p=6n<@82eRRlW=gGsW=wX{E4ksUXl)LzM^4BW*>n6&B zNO_3duHOTM-9OmuNW%+5%xU;Oh!wzZgRPE`tvYC{g#(#o*0RF%)mxi%YUo9H5#Izp+W_y;HOz{DVbD*nLa`6S zj#e*i$S_x3(~#k4^@4^BcT|TOgYJ8(sUBJ80y#!QqJfFYhBVu;K#ir%!G<*3u|NvX zKLFWrrpjWdZn9T@%~^3a7aJP{b>9WoV z=Ts=>Iu`^n2yEcXcMJTyR6Fcv2Z}S|ZWQn?L@=Ej(C%ezq|$^l zl4m%0eD!*UlW)dx5*$hDhSbZED6`bcXoJ(&EpB*9q5r--Y;*SDjXe?}As1A_9i zO;CBZ38L4lwIc{N&{8q^fT+@(*rTY^J+g)tatpme4Mt$8WF#sXiAqMIl98xrBx=M+ z1hzMHENG|OCkLT*Vq=}eRyyWghimQ^U}G)g!u#P#Xt=csbgqXh8E>`X+>9-GuF|VG zcUStn^RRth;y2XGsiE3CM9IAa+N$jC;w|^ipigMPHdG84E-qOr_vYGb^WO@Hw_FEOui<|i8a zD)@Ql(T2awZn6Q8HEo!QXw1?QI&?%%Kl@-7N4w-_)KU2uUO{)f>R<%pD-jGksk<(4 zU-uyZ>&{r!iy;451R2sRPjmd2GyHlojKBJ12$}FovzYFf#*AJgY#(z+3+Ba$iCY{D z)0lJao9$O;vbEgq+1gk>$e9arvV6L~>n3Z{lA+Gr9K5sjXtNIQS&|NS#un4zc&x1s z^Rae1OvF0r@aOGxc*%F7I%lY#17LeiUh=MX_`lx~fAxJWnm^V7b5{%IrOkCzICq~Q zJcDZ58C26PJA*SFuNIr?2|pdZcs*?w7ptd|*tVYf#dh_iiJj`{pJVOn>6@`OdjE8+ zV?F&zJN#F5#=ol_{=v@pTifAJbjHuN!xuZ_|FE5%o#||sA8LpHmd^MuZi8RCvx8~w zZNa>fOtbLB6Hg?@)<#Vf&#f-qM5hB2_1}NPntm{3pQ8pL&hD~{wwaBGCkEN9+3(*f zqKqAR8MyvHne|b;IU%EX8&ZP* zo&{#Zmy{qQ?a|JTC-F!aegb25W>>ao$#@NcrQ&V~f1`p^oA~I|cX39DFUSx@Ekseb zbfTzpidqXrJ@h`3o~=)O0)8^a)B{wfmJy<5S|-slIW40>OS8|4c(7<>b}VJZOS)wa z&z==QiTH*}!jhLg!Tu7H=}_cs%u4JpH8jK}GEpM_QVB2PrrW_3eDyWhk`GEW_Z2@8 zmg0jRU$nn{Yf~3msqEx!;lZ|DXxKeFrONj($3@)64~6X7xsRK4ZTyqoW;;q`A|L{8 zZe=9NiTb$j>79E~)JwWqFF#+BUY=M~FYjp4OP%ZG6>Yo4=QrV(z&%5zOSt?ug;YbG zQlOoWJZsu%?z~VxL(Tg6uO;c{n~Un_11}LjgvQaagF1D z@vNyT;zUtT7l58#7S@x#q_Nm{7uD0JTJ$u>_4IbGr`f2YUf*6(*K_$#8Vxsdvw^Ne zp9OWzg1(lWV}JJr8e8)=?^1hq$to+fS6Rb%F`Y55#O5GJI?qA2h2|g^HqSvy&2x}J zoO)dC&q1#91O9yPWN6;=?DE|1v)bVY{CVD~|2Cf2_^fvN0e^mX`oE3mwLYt9Kj2U6 z?h_i{Qo@hrj)&X9=K)}wLB}7r6B;vL{0_W^qg4NXB(h%mFm!;d;V6~kznJ0I6Jh+- zcZ86cwH?HC$JA%E8e#jGSF~VGAtoNPVwmi5(8+v|BNyao?nBgRNk6m0U(ekVYbvuF z>rm!YtX-L7u})?FVY@P4^0lar80yE_=%!7{n{~?YAL@wzEbH{#5_Gzg>-1|oeVtw| zHtSUEq*Jl2PQ{KojkVQjtes9{opss{|Dn$Kx3|OJ(;5GgcKD^v_*Ogo-*mQ#e{5$H zPjtqAPdofKcE*384Ss39gBjh>f_XWaQQ^@?A03z+XV0plIg?{68n(5FO-*x~^52ya z1-#_)q4x8f@WH1!6K57{8i{IfS8HZ;LpI^LjU`sVPT~w^jV|lcl7@qP>{5+doW0@1 zCm&y#!ZwIk4v*56!$D?t=P)v}*mz;D)rQ3?tP*yxq!m_G7>#|4L z-@s(L5w4~zZ7^IM#z6xPI2(f5lrQC*8gmDY%^O7FADaF7V@>{C!x2lQDZQ!5g;y%u zxxKuwtqZ?5j0`gZ%(0H!!MH@x}b#&za$CdTmvs%`O zgT=D`w7INbTePh2ZYk?NUe?#P?WSJbgbxEz%(R6I_FUe)cZZwz_J$6;_dZKyk2nG> zJG#Y(!)1SJ(XxNMrR=j>XvGId;nBjsrhVaeaLMl08*TMaBg~YrL&p}Xv0-__`xAS1 z$%-hnS43z8j+)q&rT1U@z#l#m_J={cIF0YfBm$>s>gp@w8nwS_fTJaOzTDVm^lasZ zXA9$-iJwnrS>W^ zn2M&GH8e8u)e+Fp#`YRwJuBtHl?300raLL{k**Wn4^n=LY?)TuOg?n zs~vG2?P5ioYiCC<>uyI}Ng)bcOHS{^mz`eF)8?*v!i@eBLMk-g@ToOv>wO_@HP!?E z2*&NN0Dbky_70xTUxJqC#0_0^9xOA!*vqRV45wUOA!X_GO?W+`%HN(2ur*L$CY*V! z+7rp}y&z<#1$MH>-XYni@T8QC-yGKPGaC^Kb;p>D5_wv)~okY4T zugKP?trTcKWu>&y9*`qAgjo5GW~J&*Rj;$V+f6*oX{D^*K+H6Zb@9Dsl2*5RYl(ne z+EUAgWt4*#TeHOo#Bly$Kc1kXlpZ;|1BF$x`+0IxHQD&WLAYLZtk*&|V|J}m3|$PN zbUdA)brGMsm4FehS*l2M&TY0J;H@53e6BW{lqf<<_a=NLS@HU`x5CG!l|#U;^Eb~M zShZ;?5810G$Y8Ipq&pw%xR(p}zJ&^O=0>$A+&@>J3PK5f!6z$w0^f8S%0~M6C<>CM za^g4NsGN~x)sh=IE8uSM4k-WKg!Ps7q?Biml=|$E(w;e~N(WLpklNdxly0!&<(4kF z`&vqpi{Ye!aT9as}ig1>(io>~^p_Fsl~JPBe}c0cGJ)4Y%!7Cq4u z6XdvhA_b460oE9cO%58Rofs5im4gh#4nYs%rx`FVPUhe#0{s6Gd{AZQ)PJ%_EGBMv zJ_SV#A`0D=sHrCm;9}D&16a_+6m4qS46dFqDb-K=U?U4lQcuJq2(N9)%rQ8EcUPP2 z>WM@cWx5>!hU24*cch}8NQUqNr6zRV@UwL9&z4~Ab9yqRlm>CV(^2RmgQDUb!dH@S zu4ENFA&E+GEt{FVh7E$?@~4bRumdxhD_xZ-S>RQa22s&BN? z9Djq*$<5Blex#<%(ffow@?4Gh&d!)(=`!_*sV@72yWaSg^FH#MbE6?DDv2~ZlhBv( z8oIwn0iPT~(E(78dz;i{M_zJh?{~IH!gw13q3sI952F}JG2WwU^e*EA7dFnBX~KoA z?bBXb`^*`oN!~s$W1vcH>L2{Z7poklmKWRbRtAD_<({cewr_#&>CyuKFKA$&aFP%2 z67W`qGr_G2_@H)A`4=PmeLC5{{t zM-JA$Mtf>_lAL`b;T&YyZ&J>4`{U}!VHLkOp^Y5WoZR69wc6=@4F8sB0r^*BPZIsi`!-MLY>K+vFnv(_&yGQ5w5u8I!IIkm|-;3ZJZo>I}!g)ai z=cXncy4T-*VFc&qCLH=Mfcv5d&Mg6sNY3DHdRNwcaRbSaq~}o4cKUbMhwxq!!MlQr zH{AyBr4hWVsEE7T;5`_@+eXD~$M_#P^m4-}d!bUP3*Vmr#%8CDdbi z3H4ZBLOqt3Qjg^&)?;~z^;lkFJ(ibPkL4xSV>w)p2U*p^kP8de8^doNK8zh~BjHex z@JKY_aFFowXu?fF!YiT)HwOu?j3(R?B)lq`(2(lYouqnAC#hcBNvhX%lIr(6N%i_h zLb;Q!%AIso?xd@7Cta00>8jjGSLIH+DtFRVxs$HSope?1q^okPu3$v-biQ__(|5RV zPJ_;+xDNnV&M_#=>3Uf*KkDVuzgl4UL;DV?gENp|EarU{`dMs>UYS8oIohf z$i$O~=H3H8qlTywHq6kASFi+z=-!JokmdFoQyFN7qJkfb{+TlNqP1W1CYXlRm#v?S?}?yx9e5L9$f zQ9)s36qOlVa1=#FMF#~(Q9x82(P0!76%}{J5k==a=TzO>oeiCL{@?pP@AG}hbAMI8 zb86qK?$XPz;I7{lj01Bcg^5xhSjt?Et_;6KOu+Bv_MuaBmk92%@V8K|#~(lS@yviC z8ntW}MC=)HBmExgCM?AJUB8Wrzk%-Aw-UclMSlABpzuoIeLKOHHBbIzsbTplOjgEf zz~xtI@hye;Hc`4z>*G1v(=#$>Vnh}c2|15gel>o}tV&UqU4wbNhtV(cDwkiamEuB- zbom-|97%p6bH|Mm{Cho( ziNBbll*=&#logXNq>*Ct8RZq>xR!FETz(zq5+kAo%kMCTxw0TK)?&fiuSXX*h;k6W z8I?tG+(02@dt_wbuVy{irH2h%{)+1cF4Ls4c330d z?mE-p!<}hx{Y*pJ#E*X9QAP~Z8?K@IITUIP4>#w^GF*P*XPD^FhIF3BSw8s9BxM;c zN;95N@H^Ad(xW#x!X1mE(7N0kmw?OBW{5x^zQ4goP(L4jzwRTUp9lY6_aK~WS-U&SwaZpQuBWc{E^zOtiEmM5;BiKRK-o{2fXa6`-JY*n2cIjf1( zSep0}mtK(3S)lcr)r3Bjs4V>Tp&V2CARmf28_|6jXEjA-iC5=XMdRcO&cus~esC=^ z=j7&?a!q+9w5!J71!Khy#!^=>wiV2irC@J#_Sm}SJJ7}2KQlHO8enR3Bir?;*tDkB zHrK(Pi@gN=_z2(?9rn3$7YLhKe*T^JjPl08>PK$E&V#WpfNKiFkJU2;qj%D9jH2HiV{Al%$f+m0CE`eyC%Y~Z zacUIeE8$mWg|ZQ&p~%?!@MEJqS!hH?swYz;5sL{6q7d&V`(DC7k(<4Q??$dj05{eP;#}3I6VhbxQ$}jM1K7}5Pwt< zjpXunD%+>X&FOS3y$?gMG%m@adLj2;ko#LzEVpG;ZWn_#hE2)NNR45w=~(Yx6v8c( zs_#4z8>t>gjU)+ZQ`n`Mh@%QtB&4$)ydno%p&d_q81+6L#2UiC96eoU$ zz#blnp+vDd3iD42vZ?r$U0`b!bUA~~XDfj%&PLYAE+vlnCi{(k7YFjyNK9!$yzw3>=~$!EMVQFvu0Q1 zG{d;(M3EZ?f!ikx27$*$s<+ZNDWz z(9T|D76seV5>Nbfo)_6BWfka7Wgt5O%m-LC%p?~8+w8{v#_m-7fh{p0JId}>e1To6 zB728zCH4=+oq2j_>`GuG6^sFy0oY`Y>>toFk^O!ovJcsx-QqjJb|^SYybyxFB=QN{ zNxJ%6)O`UAUkQqiLEV?^aU~RVnf|Ez1{nJLOE&5hF4(muWGXOB*;Se7(wn0{#_p#) z1o2(OUh;5f%;3(x>ZeQTr>p4~3Vy%c#V+mVuR>?ZtTHbN@cfKa#nZFaCsmo*R~`3S z@XWqTiV&-#5q~O193PCBo{6|V1<^MjF`@u*xfwC41o267e+St^!Vs%6UJGvQo8z6T zpjqfdhU{TRft#fT&PPXVf(byiCUx~NY_8tm34Xq_O0r65F#7h8^+1R3)-jL>incju$c^J!T3?WZV zc^~3kkb>oTG8b`43YM@X^911M!Dj$R2LA$ixhoyp@I&c_km-GXzVAa$uZYE1eA6+6 z1|P)bxrmMc#3f|^JO=Rzl02A<_+}>JSSXD`c4gi*ejv}maNZn)cqj$&nJBLi=xZq_ zp v=@Zh}=K(mq@BIvn_btK-j@WKM3{es1h9Pznt^mwqw`co@E!d~` zy%d0Mo+128GU86ck14fzREBGd5o5{jAp19z-%7H3lKdjF=aT(*WRD}elkDG;`zo?~ zk$iSB=6Vm6VM7?UmMMUF>;p9zQ|J*KV&Z!|!vS{~VgRr9N(7up_Gq34_#(>$eAg=n z@M~rQ%r&CK%UBG!kc|ht%@grcLrzFC+m^fEZ7H{SCTvqH z(2Z={Kbk9CeRFgsLDy$&PHfw@lgY%kZRZIlwv&mSnb_vUw)w>N6HlzoyYHSo`|Tff zyQ)szzFk$_r*HSg?+=U9H43fZd$WB9c)x6TW(tg0rbgZOA_nk;QN2*_%y|?bvvY#2659F(GRGIW}!{ zUxqlGWyXz}=pZiXb{sq7K!MN`2bmG)Iv}&vO$~mG7c}C8mf6>uLkGc{q(6h#>j5Wh zHpz%Vjg%V;n}Z)YEpV>aF^ikOS_B7U#KID5I2@>0d(87Y7OrfKO;lITTDb>D=ZhT; z=5EoP(wG1aQVc<_R?ZzJIu4Z^!5dvG66~eQ+}C` z+8Miq%40Y7Z4-m6vrWpAr9%$_;aGZRkm8gVv5PpNR)z z?u}^v@ED8q5r+WcoAT7VP~^eEThh312K{1v2&?g-pbUmCMliUJ?1_-9FH_HdrM>X_ z!AZch>OPYoVG4XMC$~uV@<;y$E1=k?$WSV=x7sytp>(?XOA<(jXn@NRO5NC~ij(97 zr(ohX4<&bd53gVmu^QQmmyQ&t8}3kp4G zke>wldUEyYFg+Eci1b47bDS9mAnlwd=>8P+y*Ov{yU)H}T+fUXYPG57*(9FsRNnHc zxdgHR>FVzMQhqZigfQ`}0T@!1_5~LrP&^S>Zl+&eW05_gJPteuUkT|cBF<5boJWWF2Faq}=}_Ag_(Xk9hYA9as=LjC-!-Q?(&9xtcL0_V)j;!$vVqtj=MT$6oka!tzQ{XbW2a*M;6 zEZt6Kir4p~epSfIN24jlnRa_u?Zl9cC)qxrd78wt;{x_n5 z-({Fp>>!vH#V_GbmR5je%$B^Vyg&8Jb?ZRkuaj<0yVBTtdxpOU2{Gz;{Imt;+IwUg zPq`4Ac-EWoyM=EKSf(RtqPB}PB!9IW%%%}kf=MC_uslcvRLR^4l2^huXW~yms3xd& z34j(M(2RWfB9Oxbm925w5P7}tC%sgLnXCxh`WW-Vs+LJYy$1g)9|+!~Yx=GKx9Q_4 zqwt%}gJ*6Wd_ee+MiegnJVXCuooTKDVnE)KEI0YcmtoFsd6jB6z`{X;JO!O^y6!zz z!_MC1i2>ATyXz`Dd3G%U63E@e_s_V&kK4rf;76QarPy_9u+F_e42UT{1vOu{u5x}o zo&?e)s3OCi$K}XuIal3gHtGyF@D_gZkv%2DL!`V@KJQ6x|jbl!(xqHrVVsb(w!&apaP! zgfCyOIqY-Ir+TLw8k3vX>|>vJ2>kMfEu~qvN*le=5kx%lG^G(K1lx3L>nF$spDA;z z<5_P3_vENj&jqv z50T23DIn)lNOY4oepAyN)O`Y~0Tjh0IbXUJ*vz*gJIM zL|-?^F!6m~%54g~_&b%iP;=gC={t-Cs4vE>##3@(!s9~kd-wd9>F!>%fn3#yeP2dT zl4G-Hj0LWiS+to?{#@DMcP{SUjKS^P%W)%wPp@`{0J^vA(*jEF6mGAg>))HEO8Z+J z`ZsYqyBtm5Ht^VjN6zh)B>72rBp7A}&?%l{@z}3)oFMHocPr`>eXFO3>G9r*rVWn^ zy>tsT1AJ2Lg=m&F1#MyK(|d>qZUlWeiaVf+GEY(YFzi?WaQ zgOdKI^40D_~Y1TMPb#?CPbE)<<_?J*!80j;FNM8eN+`Y0D1V;;0BiP(>;=u}^)aW|kK{ z+vJ7HwN_Q*Gx3yfv~kmX=2&*(82V3YBXNH7pv1-}xumaK7sDHUrc1JJMb?yD&#ToO zHmLd5hhlVt%5Y?5y}60=`&RFJdoz%L!fEfkgKJYN z@tjYuto~s%&NoUzE{5XPW2^p$nO~yktxmcPs9?0(_s&8$14n9W;g6KQhfmld9FTJ6 z<8%l>&UuzU`o19pqV^zlr>QI3hR?12R7+&JTjKX&z6JXfYoL)9!tsv$ZNLDW zS7DJNKALbe<}CF`|Fk_gfAcrDr)o;)p-5<}_axsw5OA8+z4b{9*zW*5s2u3EUn)KS zmL@)Y1w1GmtiN$Z?`rP5QHe-)4+uFf>QY*bw29Q~#r~$QMdBMCfHF&my`?o6iT{36 z7I4kGJM*No$o{}QlLnGk=dGhl^22fe)iuKM3v^71YAiJPg*0gHB}H_+vQ7IiMBw%w zRGrM$N%T%3GL0(t;D1Sf2>HR13oV_ylX=dGjd#!Hw4futSn3;LJiHN*c1KIjBj&E-ECBvnE@I6+5e7n9GF~&XC zHpA)?6|zd{v)EWkddqjenVxSq^$T+`1^zo$fOIYC+{1GxY(^e4wXcBQ!08q#HYyNy zUsmw%Sk+X{F-7Sf!oz%hub2~}`fev_Z-#TKm|G$A!$M!u)r@PWg13~x``|c~PbzxR zOs3VUq~8OQQTd>N8GQEiPfuw=?D^Pn?VO*k^i^PT(v`r)>);Qb{NU zG#7D+ikmho>X%Qf57Fuq;+9WB7{7a~v9=6?BI8vCGkf75EVX%KG_JvQtKIi8_Z`TY z^a`~kN9Y=Vz`k#GlJkqL(gCneTP11eo|FmB6tkV86jjc6qJdf|Z*=?$E{=<`d-W&i zF>)>Qr&VK#52R~>V!?I?GDI07b( z;>mwL*^W!ZCw>1AK5_~t!(e{&Hgl=>NZQM&Tg6)!gEkn^{=gWFaBXOzp7oV ztyA0RkZ+bc)rt|4$v0w^<7(SDEbB*2E8}ThwOlHn=~+5F{auSzh@WFvoo)hvO{`W} z^*4EJRhY^$>9%d!)r^`U0+7CMI;~dFqI^1^m2c>69y6<9PIOzXm6v31c&2IA)nH_G zMNmphLnXj+1uzTQi{R-qfxej>rSY?*z4ui6TbC~FKarJc^9c7a(&q8o^6*5+H1=(_ zbLJI-3esrWm|->5rO}UB<>9nytW-+pR(dYYR`u%6QN!@55bp5#my@6UIL)A=={ENE zg@c;^uXbp7r=La@@-NB89r+~!DY>ISdR&PI9{{b)I#fsdfnTkoMU;7Ip^^`i`qn!2 zULy>hup-aVMWZ%f^VCurvzq@F^_s7-ibPq=`@uHa&%e|2Vy*HjmspInf5_bbPIoie z!x`jv2%>z{%mPM4S4tZp|LB!JZB{m?uVpZ#Dg@)nxmpcYsa_@_X&F?eyi(pVyr)&G zdZ6h!#4>JTx669Vo_*;2OL??C^e%rbw)U8`J;W;a>3)*)NWBeT>{6+M(O;?^F{ma? zW*(uMO!%wIN2Vh_4q;qM*}-ao*Y+mW5Th_EezkCG44ZB-=}U}A!3(07rNNlqfvP6DHY~*t7=j3Pw~riMs{ipG)J11;c>lKy)dciNWE1^ zLn_dyYi=8+b*@@%b(Wm-q$&2!sOelXv3$hYuCPH^SNHWasrNH*4;3zcpyTmV zt7hfP_;=N@O$v9|PU5I{&DG}|V;tPy3GeAi9a?o(v9&`VMH@{@caMf3mT}8mKfFrZ z%S{@6VdW>cs#23x#4Kjg=@GQ&q~UM-5J=_x6H$mR3vmfCte7WN!py@8o+|pm`I=Vg z!^OB+fEG^XO;%|uyS)aaO_rz!*RG#>`tkYxJ;ujA4lx{f?Nl7u9>Z98PZPo3nGb`h z_#pd&q%yy|zdrhUm<9ovlMlctG&Jv`V@C z65MzqH0GF2ltBfaNj_Tln-b4GOZ>bf(D_@!J~L}4^D0HJC4r(GHrLU98@9wUSs%(# z4+hT)t3tyt+tr{BvK>kk?)>D{VDneR!vo@AUGMB;g>l~&>|Q&POayey?KAhZ3DD~c z(iXdC(D?zNC8BF-?I+PRn*3}Ak%rg4?R=U>u-r}d_D;db>;HGR7d?(@xRz7!tz>w3 z(8wb4B|Fk7$j0=oIlQG6O3xw(zh_zbA>P>YNM~;aFaB(jxTo*eKhM4_3C&?AHpXN| z3UhZg-=FeL7nr^(%#iH~yc72T+>}RK+d>ylUg4d_o$wTSP zbwb1R(1D>2Xr3lkWUUZ60j)xbH1AgpqfkPXkIY0X=iUFLA(I!nZ8W~?5|)Wn=lEdC zm^*hDk8MXHNrd8_kD(c^L}duxJb70XPikK!)&BcP17CiIuTh5@TZ%Eiv_u^2;*^(B zUUQFGHF%sGI(O#5(#P&6EQ4D}%#H96@^~8RdvE8|7b`4SFRE~hHECupYFhsjXjJDD zHx{+Ov>z1gca@o=UDC2ob59%aH!Ah)(l|3MWdXkVY#6PNJbB_9O{HIcFjJs%N#*N6 z+ZJTjBFE?-&(2&9u6h}v%EsYAOD;-%Gvs`ZCEVQVN0IHR?W#c?+vu7O-Wv!&)ASLw zVVPlB<8u^Fx#Czn4S;f5lSei!aWUJgzFn_jNrvGYi%NoA3&m;HAht#v8c2SxeUQ&K z+I>PN(#vGfjEoP)`jT3b-)}G48&xhw z)jB*GCmN5keM%qldWw3v+%LFF_^v1qK(je=6vMZUB_FB|_M5E1uru&6Vj1mpV4**g zj{IJUWCT7o6>xg610(m0cTAB|Fr)2kebTTsSy16tu%1K7^`1c57 z{7K|VHEKMv4+g5L^SXctbF<`zBu8bVG*Anr+dTih#F*iatY7YpKQ-Aui)3WZm#%U9 z>}5ET95vi11#-N|T?%y>@Z{duZywJG$JQ_cer!}Rr`o%b+dnR5QwjXqNpF(!6J>WZ zm7L!^6COjMrlxYx_#|7Mf!C1m%g+c z55M%IQg~F5oH8fSCzOk{{q@yXNLbK!eDu<168nCB&VKLGoaat*7yQpVuS4A`=VS=^ z>nmHhd<*aRY)Gks<@`esm|Veoh{mvAx`G zV~<70l1E<|rAH-?jDhK8aM9)&_1O1g;>XQu$5dvHWS`_bmBJ)RnJPx@%qHnDa#IcO zr|{`2q^21%ee{U7qTa9o6hJ=p2<+e^4MjI`u_&C@$gW9Y`FkSy=rnAB^Kc+>V# z$b*9L`$b)moaYdgugOcqL}HMJ8bT$z@}8sTimA0}CEg&OIG7<~`LJ zGaJcf?3nbcntC_^GOlaz8G^!2*O)|pf4AZ%z{h2}c9koNwsPAM=P$1Pr_w;*05hbI zI-YDnLpBogb4cN*)9t;8nsCVa7b1mZr5uxUvsHRmz^kBV_9xTs0aSrxlZof6GM`58 z%8Yl9hJdh_wLn^6P_fmAM>=n}L+qCc#FK|C|6Pqsn?2=0O)16ql+WF|W*$ricx}Oz z;?dUhR}LYDYti+f!LIpEZv$y1dRnODT`ATQA?(iySzCub8}0D!JRi?OYIv-1)9=xR zrajc*=WpqoLb;c0DARKRX?dTV4&)kZ@|^k=l1d~wEq!L)*3Sy<1R*IPI8hlZMp;(o z)J^o)9%dXS<)U2?z^O1d3e5=H!hX-~JyvQUS1(q_FJH-1$-m=AgL!ho`Y)f4$L~G0 zxu4};0Y2s3O1C}9Z)K?CR>SSOwbpm0ShiE*V@ySx2OLfBneI*7B$f9#)$geKY$#!u z?&`vg`L5H991w7uR;6_VgQ z6H^E&cgaJ{)wnXD2304aU3IvAyTG!gwP4kBACuZ~=T=mYt9cX@CK}~Gc2aQ^Gs+Kr zW?8SJ9B=fTw2_UrS#FJ{ybG4CD}~`LwMx4wj~^b>vK$6k^gbp{a+hlpWewlMvyJpCJ*zL^Ux9)7hdo1aay9u*-Qmh|DIIz0 zbM(Q%NFXmT&tzkVBP_Su2@7kO+sg6WT%1F;&?EfGTv=Vz*=Xn4xJ1`1MMq*%o^U~} zXUs%GIhkT-$&UL_{YbP8Gp*5d@!|^Qa(eX&gsId>AOx0e5KQYwWojdBTwfAx1-gnr z&k*z4f!nFVmBACm(tLf`nWM#_j}Xh)~-3SgfCft5GoaB#b?jmCf28hwFk7Pq@_Hq66c@`bh^46vhHzWx@g^wFv?9K=&XCjCz$10pXZsIqP z?5G~&)Os*Ck?Y_?IF|iVU*|evz9aNyi(luX`F<9nVZ!Z-#MR>+SvZ|m2KcjiPJxTZ z=RXf7Z!oQVI;A$s#ot^q4(V^GMZ5ksSE)ca*xRr{vy1uwMC5N~hvmPEcfqVs_AoVl z3Nf91HXVH0J-<6qHpvm4+Sb=vndz-1-HPbl(z1PD5az*IzaZdjktd4td+uWdO#sik zv~6x@{R1XGR*0I3w*SsGle}GlK416n9k*XT*TW1pq}`-9^6jkhAKRz??nxSeLXrm1 zZ-l)*4N^~to~a;TCzLp|w+&)BM$c99W`8CFUm0@`8g+t zmO2;r-lOYZHM;Cr5@u{6{nkUW^z!7&0*wUC0^xHH}G|v=oy2X{|JZ*v^chJruP7U5_FJ0a)y(7L6t^t=ggcsX4 zG+6R{vi=8;^#`+}hYlX3ys|n$MJA0iW_5wcL*Q659 z+OvB;uL3E(8HZ^734OTK-FP8u1gU;Vzq2T9YOd`mQ|S{K+-R& zargupWc$hE67elph~#=sS-|w)R0YY%KmFeHqV3u|72-)>Z6Wbpquu}%KP1Y0($)OM zk^EZAUJCVoCx+tkh$Yr|fJ?P&@eCbT{JvH>HocPcXW3;@`<4u#EBWjvO|dV{p()J( z55QAZ=(6NrsS6TEoS9C(A0vSYnihc5Zd z7LUBvE!!Z*IbRyQ5s=vm=Q~|8>rjFsR$afIxXD@-PU;H zrR1LXg(tu~!=dOi)}#z0(|x+Cs}x55NtbS&q}u;+84E0KPa1AYeKVQ^!uYCb(tT;` zp9_XWIa{fJN~Z;QyD=8}ZVYf~Mjk2C=GJHSPmrV4)b|zC!%NFHG~EaXwA|i)s^Lnf z+Z}3Cz6=p`TkhM~5{%$>8~u#k^(n3_U&yyU8uWSPW27HgYVuD(0HY zR?Q5zD`4pKT)=Hh*!TJR@1NsG*puFpu>Uy!;NshH2sTpx_*Fb<4qZq_JXOE??7sRu znZ7D379=CBYX2DpHAjH9{UpXnRRulBV}xb}x%bKrl;wFQ+FP^{6hKGN6PqHu!XrW<} zbmV#hnI**$9tf3`3vOq_Sk2*^lyS_Jwf{Kt-Hi}yp$*sDdAV%wiK&S`>8b?p8FPfC zAb0Ocij%{K^WTRk$Gs=V2+fxn^o@MYeSi%YF!P_9PP~zrz{E|5wH2Q~-38-)aO2{{ z^!%M|#jVnI4{XKww>#+|z49~-Dynz&9rSo3*>&mnJ-894Qli}_qGrEEX+`HZ{;Wjk zdLgmz*u#ckv8F7L!}VI=$w2g8&IfK|7#|#G&Q~?P^XuE zI3&*g+Z|MuRd?V8BV1i{1mrZ#Kg)A(q@C}1a7j~w$j$;bo-XoZj`4J>18h{Uyd?*4 zZ9ENy2S>Pn`4qi^uPJSm(ESyX7R*1vXG5UrG6PMUfJQag6dt^_;y78pCahaSCvaT2hVWZyzpnjOnS=3b_8p+JFD5r|9G7Vt~WOUR8v zL9jN|d1G@H6%Z^YW9Cp9u z{`9B4f}nX&A@EmmgmG7RijW_rjWf(m`i zYINel$C$z-H*Hc6qVH92!E(m*L7N@)0FS4tq7+Q%f&h*R!*oV^mmJh-Y9h1+ETefi9|R&Rlb*p^lDbksm80F!AUz8bn={ zw7>I4)FpgvJ#qhjC}ZRX1~sfo#i*g;1D|>8udW1;9^4}uF^zd2CdB__Mf?9*Q#LTt z(5J~j6dU4g5!bwAh!l^Z7NKr%uW+qsmt=y>`r*lP{d}Q%|B(ylD)B$%CjFOr10(K! z+7vBeq_dwHoKgnFU@t&AW>){6GL+xNNPJV{#ps=OjqqwkFDEMV4LDLl1@A-NekDiQ zBNM5YL^q5cY0KX-(BR&rl_*4)eCGKt!d^w!2&FjsS6n_PMjDn%7sdm+BiV+8S595k zmu-sR5oT>-PB`Lg_AdQPskr;X;>`&4(av1?x^ZpAX}5aPWM~iQnhM`9H2eJ^W(xnU z6ndcUx`=Z_vpFDyDFMF&rEmYUk`pDWjG=y^Rp4wdqkZ6xBm#z=FaW^S`u>( zTEc$z|84?>OqQw%C$D10V(kA}gP6LRB6gY$o@7~&=J<*O=hl3!*$(V|(hj}lUOJa7 zu2m3{NY3ynPPlFFpwU!0G=_)|FTDKQq!CfZNdSAslkS=~(sqe)9n8KxK2A?>A8uE{ zaJLlnYy7U=U}+}!_3x(%e~`}+_!CRGh}Sjb9fY7n&)N;eyXJ_}lN~gOaZ)e#UB2h` z2Jt;@q(=vgh{cqiFCg(fgl;4G^_Dd6%Y#98YnbKO$*n}ctciYwu9d!)zBENuqSU0r zq;!{RpfubGnPQ3R>}siWN$6~Q5u>7SV1{C|aMr9~#DI9ltMk~Ue_(=Rask9Q)i~5R z;FfsIK4T~7^l#(jIpf$ZFW~O2_pa$UA+JI!D}B{2U+ecuh@n6y@!iW1!*GWEBwIYs zmg$DY+u~CQ+oHglz=BWBBi9y*H|%rM3*)W#;<3eV^ll7a0za0A+~W?QXZ01e(b4fa z4hZKE=a^@!cC~hDX4f-pTek<`Pw?jWxW4yD(?j#Vb^SUwGb1t`5c}!<;r1r*j`PBD zV|4ln`#JLV`273dXKR47sCjQ>pbNMgWDPQq@LIHYD^Lk?8tMu9JIpYwB~%s!0R#&| zC#SQ?PExN$kYA7|tS~{F$n~+P60QSZN;v|RZRkt51}-qz1c26GpaT_Sl34dW()8w9 z1bkaqHSo#^S?z4C#+zAN>iMfWTvw;y z;X?sSj2#BEOE5vhpFBHHyiGlNFJL>HW2oRI7FXmKjUi1eD8C3U*+Q9<}&i4_OI2}>G3 zGo`Ssx~>|nyKUO3b*IVp(#4yPP{&~LZHI~uH+bkD*xxGHG3d-EAybpznqFik3_C>7 z+`R+P29CN&t6A&GRiXjhqMtcPLaIUCAZRb)CWNr5;E&Qe#6JL9kf}8tLZg^~3eeD+ z0bzZlAKWN#xuEWS))mtOYAvpRE7YT~uBTD5_c6Z?>w&L|8_NS>Eup{Lm;$^f^r5iV zixolXDL;&Ea&!dj=bfOah$95y1R@yCHMw;)1~``HuuCXCthzQd38MDMh}rnFq&y!B zY}IjUpqdxgj=CWtu=gCS^yUt%^o}l&!wb@w;x`I#kN`Z}n`1}bU)Y$Z2h16|2d*x` z2+0e}3A{5)53F{#I?%2S>snWsYh-`uG)g0QuZRYOYvx1x-q#d6FcRe&Xx|^t zL^~AY_g@MC0olO_SR;^mK>H+4O$e>jI~F!)mkqsctdP*TM4D=cF~PPMQOGu5WTn?@ z6Y1X0LUDP-(e$yN2qaTBl#p*(@Laqhaii9sVqdJHQ)I7_hFimC&-pfY-M&i{BEzKK zT5(ljR2fCgL@X!d`0uH8gmFf`7Q5D?_PDeAI-0eFU_EXkt}?ENW6MeYrsh8H%rE~j zS2*Ba=&VE7S#M`Q$O)>3gBB#^fqPBmp*@tAa!_8Eu9KABZ)hU+J&efM;`rhZ*ElZAf11GaDx_=Vl83pgVfN`k7Hul1cU5xAwckdwS!kTE6T(D%+7H^x z#+iJUb)d17zJ^$Jg%VYMU@o0r^4N@h-8JcroM@~o`2G?t%qs^8u2qO}4zgv~ z>|^u^j*qxWH%izXFQzR!%J7yKu8*3rxnj@_5AydTd)!PnWAo{-M80&5K8>l{{FXZt z_vwhgf+R0~!v9`;Pwt*sJ&z>>{-B}{06&Ek`&lvIIK;AK=H(MDvp5@zbm*tx=NXeN zQ#om5+!{DbWg2C&s^^y;O*s`k=W>41O$Er@#c~ED9nH+YwQ};|l!#>!&;Ls*Y31}QK4qB_wSkf2P|w<( zk4>>`;xsG9W0{h)p_b#&$f79XQ_aepC#0IP|3bpG%;Qv;XZ&TE$SGIEr-b_nUl^>&F)9rb7B9ezU7`sIVsb0?m}Gjizj)ZdUVrRq~Pdd=B{(jE!QtWg%yFv3EBo%daDhd0*8mCAmA6d0)kn zJHA8SI1wMJZH8yW1Lo+9^dp9OLE0%T3*K6pk8sZIl-t&#=N8US=KD|O8o3>F%MywJ zrQ63yiO*k`BI!ps^KY_Q+du9EY(CVof+|>vjHk_{S4}hOaT;TuH9%-0@GGX8#e#i# zs)i<+;f1m#yY%dHn^WOKAjJWwx*o_C-ZtvKuY{PKC^#7$JMlR`_ztae@*x--d(<<3hXLf^&QlJJN1mf+g9RCJfFbSksJ9&p?8 zj9JRf`jA5HsEb^%_07CXb_IS^LQYceq=!6137phtbRD51Jq$4pxUo&##D>)Mg!n3| zp}4?`K=~v}yeWPJ9v`ADbGKnPrVCyjzzVgBwKGT9VHf!kjJWFTH)l8m+HvSV_5x~G zxPN>KAiRi-#|J-SWGL004iAAK_O$9Fj3uH@Pj`vCYg+&}K_ z#t*k<=re}x{JO(C{i}@)OJ3ihPT`ap-XRxtKmXce=%e=CGwQcO{|l^wb$7!v3_#MJ zM1h%v7KvFsH|~ahyD}yY6(oVZqi939`K$cymWhy#UenT>p3(|osEYElyT})c8nUL} z0?8NefFKqr!09hm7*06&Qy<*+gusa@Phot`(={M9(kj||1^j~n+ z%XD2t#x70&CXLKbX*rb|Sy~=`1Oa4Ppegd>_*MUUX9bM)XRSFDl|sSW>hZH{-Yiwo&^4w46$tN7!2j z`17lahd5~xrs{Op@Z0&*xOH(JbUSpbNwe10=YkY_`KOkbsHy>}57Ulv3B&qi=z2gq z7g_N`fhotUS&&*)?gOzx!N`ikDFnT{8lyql^D;4#3>-eTCplORI3o+U)nrTUOXlR%U{(neUU4&U}=EFFJB~p6Xlj}-5q9$ z!UaA@d#mk3e2zUu#zS)WTwwD@h@>wCb?X?iWgUzk1U3aQP-Ok%m)_b8|9U;O92=A| zb67z7JCnY0JZADJDS9J#um3iBk6g_{Ma-h+F9g0$>fg3meKlnbbNaCn&7>L2qehn& zcxWc3XL$ziR@>5)m<_RlJDt{1l^S?At8aff>N|r?PpFU1Zj;{nqsPb3qWgVg*?NjL za*TA;9V#kld9=RbCukrrf>#GCD&6u&4v)kuZf)r&6riE0xSpv>3S=?U2Z_Vlv#OG7uVnK(F1Q%fngT@r{?Eb!ro8vi@NQGcjg6WMMnxSq%8;#yzEddK=kA&RapPsIszJnT;f~zuFVU@bPy-2Rih+%elEF zp_Z*3n&fRSgZ~_Rf)`Td#O%=;flD>?QuR9%teZT~!Q915Xe(3W7;{UvZjwm>Q0SFL zT?o{()JSTI+dHlNS?1H$?i{8cY=o4tP!i{dw=Nxh64Y2&r-~V78aSO{$Y(qVpw{r2p8HI-BC=5?BjGo*j*spbC> zpGdh@$2Is11b)zGwtR@|;{L;F=H2+AmQbC%0r1r8kX$@o?JbC7mBa=XRiGmvSD~0h z7K2?<**~;^$HcbR*bt>@+VwPtQ&+m>Y@;aPhx?JDloc&|nACy-U&>Cz82*(ro7jQs zz|&fp8bp&arLr{Am}$X$Y73Xo7F!HBs_J(8V%gBzM|+uKD#0?!Y~6*&_N;3|Q^xH_ z-5axrD>Vq({xIh%lk>F=wgN=;8Xg#fi}+l#ItbIeHMJ!*bcklj>ctd;EMd6@`HNS3 zW;p-x6C6$T61KGma?`fCzY9z_{kuCyAHzEmiM0Hc&|b5RpD7&7xq5M*mbaZ!E@t?0 z|CYZLSDl7pFPEjTp3=x)?edEwx5?eEg?c4EuDQL+QNZKKAFcOn(3u`&DqCDFD7ngq z(_x<4wIVe{t&g*;sTdpu%hmk69K0$`Y12Z~DD%8=J$LYQLUKxNSJesjz7<_11Ir4_mKh{Jb?3s5&F{QJ#BKDa|XVj+#(0jwHHg z-MN2oQ#mdRJUs3ExemdTKZ;f2`)87=)KTW*w_dCH*ap{X&gC9|DKB!7X(q&k@<{@- z!+?H7*T7j*yH#gpoF#!=gdV9u$O88m4Al{Jt>Ipi$8Mw$uMC%R5=TCDg!(dIs&F^8 zfbaleS-uS}Ts65Pst>%^ePhk+{Id2-1!)vb2u#EbKhA&q)!sQ^>C)E3MU?g&FJ__+ zaPNJ=!_JOt3eU83X%T?o#+3a)vWu{YvOW$m%UL#aI(Gn|XsWMuq(1fk<2_{gxxZiO;gPPV2&K@NQ?yDfoW8B zv8fPxz5PkFA@|1*gub`cpQ{xncISi(ap-3E!#$_m76^##S}?t*pT~l}kps z4a)emX@5dbGNHPM%0Bc|!e5wwOo$iK9qzQdhIWglz=0Dk_AB8%fTOV^E<0?X(r@LX&`q{bD3WxpPat-2a&v4p_YfjJZc$U(Z< zb0C@!IwI29560v5CI^|WX1nehjF=?udcH(_U1)fQX{hfNQLTf3|xLWD=sjeivV~Zn*6xcW5aQJP}fdv!{%B$*iSM5 z7=AfkyjB0Qbu;s?iG^b1yJ>0aHHJanp*`){fb>fE!+x1U&YDwx{d+_LPTYnaQ;2ky zMv%~;3sP+z-)_q{T17#9H?90vl-ZB1R#3vtb4>S;nwP^RtB=*0(`KY7|ff9hf)A zO+ir9dnjz*m@jhdu4bjt`;1Rz$z;#aU>qiIz+{lh(F%|N;oe>U5*^SrMO_4Mpy^h^O5Q2VMj}-WZqxb~svow(n5ck*9Cg%?jldd4zj@E4s z891xNTw*&8z7=meiONtg7Ui_}mg`tkTzLEfs@j~MH3%@|AGZ-Eb%1C#@vNaEf>$5_F<3fm><_X9heBMT#&F=+I~b_ZbX zYXHK3h&1Dj<-_5_xjX@o<6)`1kaH-?FG_9Xn@wG=e=}^auJGBfzV+%KlQV6$W4(BC z)DScs^cxqTicQ)W?Ad#0uU8!Yg0P^$bd|5TsGAwWN=Dm*VrHl=84;g&6Z4FBm%?#G zkkPoD4ZGt+EJDDRP>i!Z#&~%ECrW9JB0|wjUgzr)K0AXDbYBE*W=Tx~*K9hvckrAi zFOw!%MsnBKd$h z#BtNUnB2c}1V(raP_C#_3=L1PCN-5#XVp+6ZO z>~Ws-v%^o!iRU~V01NF4Ue)L_-l*F?ChO?|RD~Kfu(A-)w%ln@W6b(znxf8}mjz1l zgqO(M>YoNARwK93mPZ@v!Lq9)5Bxh#16Q(*vdAji{G5z=Wmj@Mpaj=LuDPSiWyl?s zDzgJij*x9vaNF^BtQaF?5`v^8ANN1k({4d%)FiwqXda?w^04YKjZoMh)#*C`qXl8M`;Xu6aMkFCvB4^dv!tvK{Ia}w$H3+rU9ap+bR zYc%doCuGT@>d7mON71R;PxY2sGI(0IVE=Ur;ak$NxeBHmp&Ll#fi%Z=u`PfOUtkh* zA0PWkG(T^SW0~DNu@%Kp)Fqu0tKJ92%&ott+#lUarF{N?xy^T3dfc|zg}cH@7E#jZ z_Uz^+((9sFDa!6F#67h-(4Je6LoKFedI5KcqA9%6$LNeKtbnE`WM}uk07XE$zX#r! zrg6o=tguIvn`y_u8*Fr6!QQRiU;DNDZ@+q!4^x-JY3agI#&vrBYe)G*d!mOMhSboQ z2b>>Cv6Zn=RVP)gce=aL^^{I;?ZZ z!!nI^O4BM%O7N_}!JO?qR;#owwhIfjT72*VTXsVa44^_@=fK&*b&IXsA>_2W6~`eC zdCa7r$Wh~bsl}e7EQ&ZgMdsJKQ9q*xdz#?tKipTX*>|$8eHQEs7&_@o3{*VD4_&Qs~O+}%xyV=_b;!~SC0R`zyErj-*&w2h6_hz8+ihnYswHeuk*gbxda*lp0qTP(-dO^U55lr$2Mw2ENIK8Dl=@$*#ffK&U2T>gIpZ@& zf2s{)lIn%cTEx8}23xkChIx2j-`XZtUd(~#QqWE$wdywgR8=?;n*u3tv$xoVDV9d( znl7O^<7f)z=DO_E?aLjKS;Zz( zGSP={_1oBPo9C>z&U3O31Uf7w8Ke74zu`F!aq?GXx8fsKH8$t3KgKc02kftL8*FP8 z_Ua|lKA>lcrx~aX5A1pFsyfFIPE7go&fI_wJxD5_@*TplONvJ|l!t~MO(YI8-MkI) zFs7!}k73CTv=S6f#fS$E8FtutwOhKh8&v&of(>x29i0A}7-_PT z53z*SpDoZ~w|yR_HgbeD^Js4lVI%(WhX%MoFr>eeft zo?cz79d`YeB|D5MxMY{lx&GSda}H<21nl+@?XLyy?sVLQ{FWA3s&q4RlC8_t1@Lqe z<}XV}O^4lrivwE7y7uAN+B(V|gS4U<_7_vEIF+$hLYlI${suh{DWt0W^;Hh6i*Ra`i^!$!PY0BDEge{YV%s$QCeZB>a4JJ-6*-Zl+#xOc zArRAgxupFEaw!})!PL^yDeP6Id|01ULe`ez+h8!C*c}ea2W`1*PO{f^SvA%r=dQZ0 zdHBTsQh9>zCa81hR(cj1OHjL$NOt%O?Pfj9%37I?Iq=Ri>tf8`!IrX4HWye2W5L~E zqR#pMwD%rhQ7lWt@XT!9g=H5M$u6P-l4i*uNX~*N$$%nJkSIwo0xAb{7PFvYR?Io0 z$Ba2gFrt`I#Kd1cvkQxQ!oBak&w0Q1`3GjEt3!2nb#--B?aXvbdODT>e_7NQO)wKT zz>tYWLzzH`NrgO_=*#VJN9EnI94dD_#A5By_l`oKwrEI+hp;pHK9&KB^#goC5H|$U zP))g1x?00>DTG!VlW(HQ2^woD(mM`LkVFX%(c z53T(rj_!Y6J_O4EIPKSEP1=_I)4VLyf6ONc+5*xA=#_zGQ0+pcZ*9EEKNHG(uJqS|7qnlQVc+u%-(vp0o3m1;!@)ju>#65ynG z+2`kSJ_;20aaR2y4Z8n~M{%5jA)HC|>t~#p&Cg|j&PCI%CxvGSq+uREm+D2$w@et% zXlR`qHLgP-O`ao=!bj607W#*ocu{l>{y{d-y`*Of%14hz7^K8wc`_Q({SKk#x*Wfp zgRqdc^F~p6Wc_ju##8e^KAyjvU-~43EHNw08neM{F+0p2bAUd&1D!o#9(n&k4)n5B zEHxVvkfg+dOuPB43$FEB&_l0x(}4+Gj3L2rrUb{iEVziTNd@y+7(wXhusDQRLkG%p;S>^j7?Teba5;E; zv6HMJbLblRTtEzw&>A|8!NCPg4#DFwIk-5I%OTo}J#iM7MctsqA~lT5;xLqX0v?AY zj#OcB2`*1W;37Tv$Jl&A94XFk&*6#0k#tEOSAIu{`Qk_@P4EyxSDeL{5a}$pipg zB@R=yV1leK&fIz6DLjytt2!+sTiV`H;2x=HqQyIEIUJOQ8To_HTbqF>W4IGMW zFD{r#j|f0q2?IrPxk5fcBT%5L8clo@%i|D2x+@gvJ?Si-6dppz<+4#jbah}1APhKl zppWz@s9{2ySJW_yZWInK8+xmU>2UdYd(}{g5kMI_q`{>sl~JuVBrB@H;R(eBb5&5Q zRe*QqQh>N%C3Fw2TpmV1jE=Z43HU^Vg#j5gfV6}Pq9-sERE5cqA`Bb`-BG%iI@GYW z!gRGxEg=*KtOmVhps|J-V~x02Ml6as7)%T&7%V=pFN>lO+!4TFqg3Ex4udNWMr_UG zQUN|R4n`gRfnrQ_0D&E-QR3h<7HEV9DyTu1WQuT@G<;kGD(9jLUqgT@ zl}%+f3hUtlRJz~>6(;m>UJHQGt6^%mGF3(%tAr6PbVA4(kc|M^uLXI-6{3J9N5JK( zFuX(z*+m7&LJ`VT|PkqsQpsIGEGb)^{<-Kepq_)(V5!4(ov zSsi+WRX`faC$B3`&zK7>?C465IK``ov7ezy$EL)p3J76ni!8BqU^Vz?uwnL#sA(sn z(`1P-=sH4*en<*xXaJ>kfMXD&!JI%81sZ99^ggpNC>6;h4h9wBEFQXxSa9bMRD+-+zKDLP^<1>J za1njkED65xcbcf5nwo%B14bEm z0Yn?rfWmy3Igo>jWC%FS7Pf-c(o=+P2kHg~m=s6@SW#}Sn4=8n2tya*A9)>LY7QY|lL_$+Fl}{~QcTp-=F+k-9WC9-G z=V`)4pvmDd1w6ip1@nw0F1Q2z)70eBzytdB2)f4NqYD?Nt`JTh45+x^9Lxf^q7f{C zc6E?22@$o-0k3ddLjvfsNG7-0R9*&8!XQLK$i!9QuyoM0qXdR7B`kDMJOjdP4nq&; zQe?tW=j)L;LgOYxG7%^P@`ppvLPn38F*IM(6OlzN3TS<$b5M*;FUz=0a_ix=ki%*5 zMpg0#wHYdr7cF>8s~uvP2dxlfY6okvhFF8n$CV|)6cTF)QSZbWB6?mD&?P7g(VUj{ zASnoy$V<}^)Urw~Flf5SbO%qm<)h$6&2(3~GU~>bDI_qAxDEi>vguTU1U*}i!67Q}qMQfpYO z(F&lEk}z?E0%;9UJJPE(lqF26DIzo&5>*aMmYwEE&;nHWM4Koy%(@Ij&<1La2UN0j zn7%NiqBg?}Awv!{T3qmnA_7;|eEF@-!i>qXQA17wRiIvuK@qnT`R z!3U_5fwVvYC1#LPjvB?_0&}89eLyMz+^Fj}qy({`BUa)IfMZ7%D>DYXW)!#bBIJi!r*-AJjSR zWJX4t18B@Akh#Z4iX0zN3~|9Xis0V}+F<(z3pY;}H4QC{1eeZQhIg~j}aUoYeAh1q|^MPE-s6r*Go9ECZ0!4u%5K07~N3&V719T29odAm@ z6N&94Qb}o~JPt04gv7#)2n~kGLNJVI$&r}? z1eYzB2xtxgdn!S9QR_FmM2!_+*YT@_Q2Uc`S89LRD-}5q~v7K*n+Wt=cCakje(M$U2wg~Y zu|^kDbdjKo2D-FE7aerzOf4&DIYkh<6r4jL3W*Z(73olFH`2~`kbVi3IHME^5kX?S51UdYt9@>`J(UbAWk*uhe$T%4*`>e05rpptit&$ zgp&^`Je~-292~i6AOq+nkpMysNb^BzN+g$#l_#4b_X=njrXppYEFjKDdBph;hA19A z=Rso!xeewI$Zrv<6FD?+Wyr&!y&WuM*s&Qd?c{i zt)yWzXO(F05T%SVlrf?eV2BkV>H^}Qj#2_@a%p`QNZJa>lwm|`#Ryq;SHj=1ptMiB~50rh($QjCW5QlQbHcX zr7@B;5@iuiv;bThKiL*P`6GVvC;W;rT!a!C40N@v5XywIw;`;ED~obfh!QJ|2kmuH zf@MQaQd}q^6v&N>6^5ftZdb+JGHO%CGca$katoYn5ew3pxUlxj!az zf0^tF)39KpLb4~tbQB=u$@o#o70U4f)I-h!J)8$?1}LrY50e{ius~8V5a3}f zDu6-^%5NYJrm{28Kb4)qK#a$vaG{fr=7fl{l;!ah04&Io0{{vTcgS3NC?75_&qf|Q z4KDK55lBEHX-VKJEKPJ1$!;2ye?&tQDRew^5kOXG8uFuvgQ+kQPAce*5#nIQxW%6I3GktZxD6oOA_xGGRr-t`tm3I|(lP4TIZ` znw6CALL{RQO)p#ywzfr=rcH@VUgNY|f=1baULr@)^mA<~N2!36mqHB;&lWRPc5k)j zK}xoU+gkHnWd#6v0Pt2rza`A)Q|l8IrYDo!_LQ5p5{v;S3+V$47GTB^c-! zAsZ6#9LxidaNkosgGANKVO3;PTo;J9Ef>4M@g+M~dLR{HOFMvCb)+x}>LCB-WMTQ%f zhxky&Q(%zI7Xb)H*^d$5eu@ASK^6z?R>*1b02X7iA_Rj$$F$;PwyA;L2I97X_y8%jAck_S09z5@Dgu1P zx>#-SaoRw?Cu^sm`1A#O{E-xA`qgm^6>RF-HdOSF_FTFMeFWr>!ubO?z<9&+FaC@+pO zEDSQg14wllLs0|;J5dgacpM{{)no)#6T=93WM$S700h@arn0e&C@(r!rV>)|vLD4| z`k#^fXLFQB{WJjxG^ljyCuk$;mwhG|nV(#w{h(kftO`ONSH5aO2|k4y)d4LMYw(QZ zs~ZZ*7B?eU+>AgcG?KLxwH*hDZU8h@M8#1#b)cNw{en}Q8DgNOgBc%6s7GW*X9Ov{ zct$-inuS9?dgCWPj{6?Vj%_iA#x&ky@L1dWMJeitr0^^YJ3>q>!E& zofezu2#8bSqqE{IEX}26fgyc7B(5QuvFJrEM@eFKc1D(?g~gDh?8KZH^VsxMi@5ac zwD@d`*!0Z!gglGv%=mbVSlieHI|tIz$~vC3wTiK~u}O%Hi?JaStP*0RF;=k&(Xn<` zmUcF1qb0OwmNrlek)eeO@(*8OXe%X5AbX<_y{N_v&CH3XV}mo%D|misG3j}-STs1) zC~|SxCSGWiJiXk*e9+!Rm@oaZnUS$1Jx!vxg@a^x63{g|Wq5RcmLwaEv;-pKB`;8?dG9^(D8{WLH$XcF}(yrX2K{GBUv`bp~1AUuRj^u156 zJO!#@P|SFjjbYWNUmrx{J`>KAKYUjl)gGT|DoM?PX_b-`V=9q-XV2N%oJ4=764^`s z&S~^V3{54$IWZ|ou>tYi)7CP#CXAV+d zBi!kD@v=C)I~4y8xOTz)Jlt17hlR53@}h9G%Nv{k--oaT+zGh*fmv(&Z$3B)hvUEh z%wtC=ZvXE-Hkt^9z5g@MZH@y}eg9hz#vVdD5dF`e(o~0$vi^4-5d|rSb^H5IcqT)3 zoj-dZcL`+h{?9z$ybn+X|EC{u<^o%H`}@xfyQA!X|Djeid2n6&B^^nY{9_D~;n7(j zQK=W_&2b;})^Kzz`ue&gAsxN#1OgJIZM-BwR*rg!PLi6Fl`V;hmqbhG&u<_ZJdzwO zNzas|#AjuhI~Fd z^ny^9Br!TSUXm*N#tn*&mVdm^9Pixnr6fr#-5wxC3VLrj6KDl1B{a$$C%w|*B=YYG zQDjCrGwD47Byl-t?UBUGUeH3TDy~B>RZgKjp!zI88lNVKlYM%`91r+u!H??XLMwKs28i7PSGaYoO`dF`m0X8 zT0Ohp{k{|CESczU{7y~CcfZ_Q(xLODt~;i4KAF3g9Ble3xjC(GAD7H{i+*#44PKsm zdsY4YPjyq`YE&2Rd$oN^xauQ@$@vxEoy#>dCcPiZv-;{axcOj-3EJ=+J9XA&1BM3% zqh&`2W_SZmU=0s(On#sc`tc5J+bCiXnCLO+FCm^G8OLo7emrn8Xz8`WuLaMf6Hq=c z$4IxxD5RH0+B-yMMbfHnB(Qp9dd$#Bx3v6TA?9%P2o5uskuVskyXm zqIpJK4EDeN2=R48+b7A$Q$0vV9z#nEIml&iI1ngen=h7T>y#5&E3P(%iG7-&p)7NU{J5%-hDzs!@?u__Uj)V z6B`$wFeEW)XmUzwT6)H?%&hF3+~IloBSUEUpcQWYQrK_QlaW@lFGjj{ngnyyx z|K0(FWF9)DJ#FcZ43jk*k1x44*F(sfYFv3`)%j+>j(JBvH{SYf`iQ63%i1kEuD*WT z>&2D^3l48onQ(7PUBM}zy|bUJy1eH29%AL14o}9Kl&kNYacI$mnahn%CxjU~Ol{0~ z;2K?IXQO1^WO~Z!Ve`B`lVUm?y7qq6%mtI~H7)t_V$8ZR`C~?@()b{#?}Ht9hCu zV!L=q4=?ZjXwdp;IvY11A383kx_(ilpJ4CJJHw{fI~4hp?#8}pEtneUIimLAzfAuY z_K`)lKls%yHWBh>fS`m zrAqDc*o*F>iYw31z1!3A$V@6|kUZIe>XNRFdU)YPK@nyaJ7i-(_Gzo25fty@&a#G_YV z9;p8QAd~UhRu$RqjYBsjZVW7 z;$yJX=u9j+1AU7t9~+vJ1}EswIYY3lcu*T-v$3@FTr4g=77Ky2K=g6A98lJ&4R&%c z@604DBs!bwGLyp>irZ;u>vig4WNKlF`2&7$zz;??<_7o!0lz=s@CW>EfIkHA_X7Mu zfZr4F+hWN;{HqurcfoV;b@+X}9pOieA+`~9gdQV=QNlRDc*ihe4pi8_99cR}a1KDi z8BR19JK?+vCmJAC9PK2Hc5TM6G`wv&WYhJ>&`#YLRthH?kSiG4ahvi!VI-VEaHh)2 zWkK6h(RU@G|HGmG+0g$4=zo^1|Nn0tIEEfO(g0rkF&=f7{6#!EeBtaXA+S3NV{nIw z)RS;f?4#i71=c_an0URw3PPq{5SY5XsC);QufHQaY>bH!SWU9Lyo>CvxC6cX@T6)E zr;ILdur|;evB-Q(00RXbovBix)VsB5V0EM@7`F7WndwA5OBMq0nKFCjXG|JY9CoI^_cuqN(!eKo)2$>U*2BYfRCm6kEo%)WY~i%T?BFhit2y-DQbvDO zDC^f^j;B%PVry^yxL$KG^^jqS7|9%P^pw4~oI>?A19D_imU$w2Qx#haH2C{;F^3d4 z3cExBOBMyiQ|5FgN?JfI=8)42`W6Cn+k+|-0=Z&a z+ytl;8i8yWsVsmj;BSb`os$FYFo(QoHdsJz4`pD86PL@N_M8R z>xL#qr^IJTLPJ6%ULiq_ZuZtvGi!HuYcmfw2PL&a0TK?hf zUmI_lC22dHG~3`DzE|g>>i3k4?~IqfUw;;Nf8L9&%v)Eo$J*3f>vEnIsro+LXX<%> z&Hb69`>qgd;q^{VA5|>g^)PzoIOUzUdI}@U6E7sL>i_6b$->;)Wur<09_WwP+JE=C zZ*^Hoc#xgr=9BKO-qStzUHWa+oSmD^5BvPS0WW>TUN`W_ejDM4^O*;1IvI}__dc@r zTCdH!2aNN7Bq6t6%v~|St$wHpw=2KTon6!Wgbi6}wB}MY=TbH1yR3=xMJM@Cjqg*n z%*dx_=f3f0NURRMJyx+TZsHPG`vn9rI=-R^=K)1nq%M$DSIAUnwyQMm5gReck2}Ot zudCqOx0(vw(m0B>bPbpqq&YU%GzD{j$wubCu0D6*3fM=*SEt14zFz zpE9pv5A+MPqlHCmW{P=g%U4Fx@6Z{^NhsDLgWk6(%c5l%sn7nRK?G(shb&}YHW#KQ zi^ailW>3`E+Ma6*?-LO z?bWB={?p9YnmW54Fo@Nka-^bWOYXL_soEclT>8%Y&>_O%_1(UC1I`{hJ*U0?an+P# zUp|R<8;=^hySv#{b^Y4AgM1Dw7~spV9A397#?k$^iT4kO0~TU06ySQD+a^wgtW z4_|)on=^Uv2A>t@GJEztMoTxnKFbf*G}fxNHr_ubyf#;SsD00m za}o{h_#oYGgLJD>kZxPOkjG9B|`6U=u+)!Z)qRx)i( zNoiP5UA-P_ll;uoVw=WPRjj*wXzWprgFcyHJGV4_^}Y2KsvjrRB^o7lU8J>iS7m)j zUV7D8Df!#SMq3lowV$tdLGLx^lnU-X^j~V09ajHjwdaVdY6lyRb{?(t&Fb6}gQ$h) zt{A5hS1tPwH9Wuh6h3)QThp# zhIC1vq}X(+I@u0oWvMA!S~}R1RwmX~b`CaV8+ms|{Ot6l?dpB;Q+DQ7>gs!XF64J4 z!)bZfiv)>R1`@B>>tB+0z`DS=z_U@Ly_uEN3^fJ89q>N{QN$M7J_OWg*DyZ*wAu&#S zob{SJ=VPZXNzTPSjI4Ce<{bYz^Kk73FROV2w|x6N&3mg~tp{6k{)Az9mzUPvo~!OA zwazg0n75o5zShDy+CR46+tSe&`^+6YVabZI zyHMh?R#mN>%qSC+MXdcG-d57$jUR2*Rg2Opr9VowC`wxJd9%7soc+!;4%bv?0O6&Y zNPAR>D`tYCnC_(?K@CKqVz4p)JHEZaLYB>6uB{`IPJ;NqZ|0UQ!1uOORcb zGSCu%|D;&`D*?7OvtOhp8Fxr`;b4ixeL-$WN)PR8>1WTpeV+WiR9*DozGL<{tz8yn zmi5i|j=BdKT+PI8+eGjup57$!Yj~5mAuwQS#ew{QVT*h?x4w0`za*#R{JJd9vDXW4 zzd!KKcIBx^uRE0+ogWw_mTIl8$jl0V+hNY5Z#Hu>%dX`{=?(W9H^E;0Le>D*-XVRa zR%}hOxTPuhJ}cX}HrFEbZacEyr%O{~zMVN0TPpTlvpoZhkOcu$2n}YEAr6ducWECb8IIx&h zW%FdVNPC>gq7Z|&+Y(10EZ;6lgD!WSG`D8{;O=Xr>8qUf-!LOJTQapHm`Zwl>Jf<; z%mZ_4Bg=#viUzxe8RtIF-F1uQj-fAv7HMnz8ec@^ zyzJTC?7GKB!S^$DX3`Y~XGaCkFVG*j!P%nc-sNk;7eCC{w|o1i{2hLojXj>bjXhnX z)FJ6i#bSxsXF>3>@N;Gl{V(m$c)CV;Iin){!R|=`5%1=@FMj*}^{a=)9j%>qhcA2+ zVlbiG$|9ZFwR1SS?`nfSO({S9Os!&O&`Iq}(=+FG8yyr#kZVKEc505)J-2+y z0mH5NvEiP}d!K8nThTZC?jpj=(;}+j)}|{(mT6yC&Q*K#BI)Vc<)#Nunuvt)(-z$R zu>7-XS6;mRoVO!7`tQ3~6aMT%-aL)SQ#R^RcW3MRO*1>V(b`kzm8iWIHt?>^0R8Iu zCwQ+W2&eQ)6{-a}k23aMoO$tm%IPEZ87m@YMU0*^wM^TW(ZBKhiXr^$3fq@v79CDL z$+S~#NZ;Z#q^POS)~QzN@p{5ZcSZN&8q%x1uUzg>mw$}8{qh&n`yD4O-N65%X6U-{ zQB%#@vEKVQgMH!$y9RA`uMc{;EjRxL->2FewT>NJFrsBkLN<+=|aqsxDIVjS~Ra#v_`buE|`0*%9$);b3lH- zmdkJTMCzdeOy{4F-=rOBO@hR>u_BS~X(^>ZD-wbKoYDVR(tBBX%9i`LeP?wWm29qA zbD;L&@ddpNf;U#*)d=dW^6KL1i#<1HlM?X@&ehPl?fvFxyU*G*Ka%Wv3rl`B@<9DW zj!L7DIseVXvmMV^b^dM1yM`e;re8-sEzy1cG-yTn5rdG^Q$Ks1=Uo_7d113Vb9vLM zl-WbB8{P2^*<5_#v5~jA;fCT~VSSVyF-*S?g0*GjiN(=Q$K>5|%e z?yiv3KHI%!Ec37AZ<^h{4Fh`LysYoIw^&{k8Zlk6ju4UuVxEQT|5ta{sc5jXksaHgMF; zMi(#MurKf3+40`O z=P{8k>hmW{TxvO5mQ81+{<%_TlT5+M=NZn;6ZmTPkMg6Zy}7=-!;7HFV~^XI3|evM z#s1L(_mNjZGWB1Pr}yQ>M-IR{@Y@M5-D)@ggVUabzT30a@I@jSoB74!gSwxk8O{e>PPQ*xN=Rl&F-M%!wgir z<_etpOc~bS+oRq7ZQC{n4mr8Zy}2M?zhG&5GU1uK>L9I?OFQXb@TfDX+t=WG*7V8^ z%YvR=yZLsG>i<0a^{RUdmYjA>KTv3x%@)7P)jzbT=!jwH&MiZoCzj_%Z%->%TXkri z&l}bBZ<8!jwtm0g`{WdZQwax_=>Db}M>v~R_M5)@k^bWyn@`7X&kJQ;aWfCzFlTc` z-ui82^K!Iq&iYL)r;~-{8g5$IfGJ%LmAxK+TL0P$y}!+ z6)s2Wnv8#W45^Z$OBx!`3JIh_QZcnXQU>J(nNko+pq%>79<#vltH;2d8wU<3)IT?* zBk8VCL`iB*T9&mdQ2qH=ymGAqjX#=}KP(x{A{|eC%?&|mJvx_FPJ~j>By7JNXejBcz=)_(VS+%HaOo&gA)r$c&ua*pa zaDaV6oE(yC*EQKN?%2_SqCQ%;-hSa1bZM-*!Vd7>GLdcV*@wL?WMahbLXGrY?!`Nd zdu;!`vH9U**I{e=ZIUkNdFuSOu}_YYC;w`r-@x`IxJz3r?WjSdFhEHCN;wj$BFbp+Vb zBBDJ+i7B3&_K&Uczy8%hf#U{}8j1`jX#JrChss-0SW*?rWo9k4v$T@hSxfu>#BW`6 zJ~pK&#rC)yXuEOL3CT&#t-VM8AdL~P?1~CZ7q8Gw*SI}vXO}zgFAVtJwI*v{*wmP< zz55+Wwu>3ivuBpe$cx(wZF}Du)${wrP?s?)r}{VXm-km5{VIIk*$#!w?f59y)D4%l zBQFk)$UJ&1yXi7#Lyc~AH@$*&{%2o1I9Tmaad)|TnbUvb#K%rzJ?(FNau4Z;~W+;vm9bi4I_&TX0%R1CN3>9D1f+8ZGNFL zNQI~*^b3^=BH`d-Up$_{Bw)Ick!^mZLXMz6{FO@jLs_PT$G|dmrr=VOv(DTu2tNnn7`Xs^HgU4CY6h~D6O&arG zVQwR`E6v;;|5%_(kpEWExl7tx+bcMCDe!-(bNAw$T-ztb>utX$HF=MkToQa{M#k99 zVQV|_6RF_ORG%B}vbmo@aMbS?t#r5>A-g(t=%JA94 zhv+Zf*`Gbgr}%@@Mc!#;=W|=@%7gPRjxVXjojQH3oX0&oaKYi1FDm-apY`FSYtYcF z%6kv9M_i8bF5O={#Ax_}4M&7h_34-j{ykt&sLJVM@h<#_E4*)iG-Wty9!zAZFMcxC z`q1j%rp7yTJr#T9_3^t0x_tj;)L>nlzoFaJC~{`^N9~5b*m9a_AlI(P07XX7u81zk z716@YJ-PTV9lbsW51*-7l9XCfj$T`vHqH^>w7AE? ztjk5~I@sBD+L5~EbPh51kAK+ur6!x6kwt0Bif&lMy;105M%tN?_LQm|t)ME0ks)Mn z1y$MWFDv-T)BAH3*`PPbEg6EuewfUZ!o2LmsSsrs<*xP1J#Q#qToyZz9pIuDdE9En z%Bqygj)(ERFXHQ$T8UIvZy0dpz>Me)Po+<*x^Ca_!SJ&0?BbH|sx~v@I$caQ>%PXc z{T$;(p)5Ccl{Oj;#RkA_mUY6 z%|qQ)_VlO|*3bDmwP0V~Lxa_M1Gc7iZ0dJp^v;V8r}7_+(;3Xa<-GagOWQ+UoH}jW zw8zffS&Y?JR(DaI{v>yW+BUEL9@3&)H^y(;v$#X=(qs+=El9Mz})43jkUUbFCY z-NhHyKF&FxJJpA|4Apc<7S;84nbu&CM{a$$%KnVa)OGXwb#~qDIAkR!s_grX?tW@t zlxkiIQpW{XzZu)(!A3p^NJ%@=-jcL&puH@%6euMT_>V7A zMa0j`0fCkS0+s`qbL-!H&J^jGZ@iJVu1FMUz4zVDzWU4DwYw$P^$%XRn{BVf^xHeO zN=fgoUGnd$Hw16&k1k+uKIw23ZzpxXJW)A6?zb^>26s-WT}}jG=f)oeO|xQgSA+73AxWK`*c;cc)Fe&e14nfu7Nj>nKN?MC%!+E`ra|JT)n}2 z?*sd|4QX*Ud8^7|Rm?8C&i?f99!L3VWPXL8@l)l4Wop9@&T)SI<)KM`QOCe=qvazq zAE-L+@*8yH%W{)jX20okEYrNLGa*KYCW^^~(WYzcht{&elFK=Tw zZ`oQo%YMwIB?YD*g2HF&+jOaNNQ)aAvUjn{Mook9XBzf0il;V4y}8im(3Cm9?LVxa z-6cxHXy;i&Bl|A%9sF(2kJ>V8la9gawF&jn9f#H!`7MbmsqHfGvVK61KF4-MxO8T` zxj15g#Z`lc83R>%dk^3C39H$^fhdZ)eYpL$1KL-@0-idQtJE3z?bq1tIm+wNk*drQ z4>F&2zJJJj!SUBebs}z$n_3^}N3LE!?SB1$WtCs=ZceB@Qd&6j<+YaqPyLKns~N3Y zJ$gvNlSwgoQCls>UyoQEd1$zi(c71)RYucIr@PwqI#M&ibK)^x&*N7rJS?*3Hl}^b zlk_!J8#s9G!XCY>#^2gp(&66HpoV#y_j{M6%)j*DTFI0aXVXhq4(op5FKS)?ez_R^ ziI=~PBkCtFmf|v(Y34{sXL#&s#|o->zWRjpqQOLKvOm4d!AeB-Dhn(NDE9l8e$Rw? z3$qp`Ys*R$MOsB!T2hPMAce)Q4;f4bDJ*vGf6p)UC-}3;!eyxO5@um3SvZF*oY_Jo za|T&Bj&zY%N8svKf3>#8rN?GL&yrH3GxK9Jvdj~+Q%Tnr1O#cVXDQKDc#p$ebVjNL!E3YN(aV|pD}u}cW~GZrCFmcX$9!K zcXFTH=fdW1$q##Q%#9a4an`Q5vO{yt1LBY-yAoq9h$_wVPV#?ExUxFkHN*P()lPUU%GOZ^eA-S}HvzN|UB za^R8jl0^~2!h?Lh4!fUPlskZ5;G6s{f7y`(si{Lx^~q9G9ua&_TGSq_hxS7$*TLL> zdg1y*3sAwZEGs;MeAIGxfF@JQK#l*mU0D{2u7yra$?i2f^f#nTXpY(6oE~xadQ#o3 z-%h2UH1P}bJ8g0 zTCV=NZeFXFF2rUgebesdHekIenFpnJ*T=M(PR z8;(6I9I$!tea!`$mu+@i9q2yqRFC|*iPF9itS%=~YV^7~s%{P|S+dkD{d-Sby7|pc z(G2e`@zJrajHlDsJ$;``F5D?uaeCzAAp^XwZG1OOclY5hmo^=*(x{vrcx%TL`^ReZ0Sy zG)>x6$uvz)&&(WKD7n*yn4V3Hag5Hbmm|!S)s}eS3n6Xg?O>`16_9`8>L2cRlML=Q zD;iQZD5}HDHI5f=qLu+WNkq}Xc(do;RCJ2o(x~MtP4KDxeZ?XbXaqM}Sgyer0%03c zdr`UDC?amQE&RM`gjwn;L7jiBv+?_J-GoCty!d#5euH}ll$(?|vI?i7YBlSgjv_!1 zn8>s+mfI>CIc812@t=2yf`GXk@~=@t(P3EhltFHj+5?fVd`tlS*^*Fn)YRQ>d@q5j zRBm!sOjd4QiqfkCM|ZvbnybXYpA36QBGK72yP4N$cIgRcT=QAFnU<^ZoSzkbQ8)-M zF@$7ZW3}SMBjT)a>06rX|9bVI`~Q}XoYHCYk#$8)>8P)n8-3%lTOVGsI9jhVC1+LX zV0C)+;xO@UjxM-#hYV7g{(hJ0ddhfm7>tUo-ijoGVlPNv$LYG#JFRtaZQ>&06#kLy z(!E3seHVMFWzZU5Iq`itLsaXyz6-{pU@N)Bmd|tXTFMhH_kM)IA_*Vv-#~Mvwq2c~Ifz|W zZy)G7S1Jo1^07(SV9(^_2yjc}5mvr4?p@_NgR zRU}ZbzQ`SD=teyXNN-h;uN~nOl}(s&yJc`lYJIV<9Qr|09Q-MT+X`0noG%DHfGo6dCjn(XOSXMDX+R~Q*Z_289bO}H46`;l2_oAn;*cGehU3qW?=L$7SLA%zm=x{}`g~h2F|-WbK-pshwRa3{y5qzvWKh*}YO0DKqYA z!&eqXtLUA%*c+?)W_f=2lIkr7jm(fD(y2n*&iE34^I_5L*@(+r{kuhRJxr^Vqv}}; zcN1ItVLL(cDtuB)2XAhTJ6E{KWO&G7N!7K(0x_cbT;+DZRHbkH9U*bB9=*L_GaI9k zvr^OX2_hgY6eQV2v*`K}TzDd)1h=IUZS|G1EhdOsAL_q%N%ksr2id965c8&cnTl^L zce@_1C{>^5<8-{!2CCA93*Tvwt8Flkib%QH;kME0d9!g+tk)(LWkN z>gCQs$6%-ZMM=t6(U^a0XfKThs2Aq;?2DApbkJYo z#=oYUu7cX+6`k=#Xh462dzPV=4%kb|v+M3Dh2>V%=}>BS3({bAOMRf(J*Bj<-KL+T zv=lYRQ_j^^6O&s zj%hKMCN@f<>x|oU#P4z$iY4Y-E?6gWnHovD#Uw@Lmm>catgRoDuCU5}Nv6&c(lkDJ zaTEP0xTrBefcATEBLL{j%yNr}eTa~jmw=OuW74q_|$o7{{EXCzYD-?|!e; z0e$FG5~_*k#nx^$=a;~zJ$IGsjoVxzMV4`Eu~@P!Opo8eMK*UZ*(&voWBtXS)bV@- zt;8LXoC@8SAZdv6Q<*!nZof0OQyEdl zDL)~*1C%s9w_e=S7P`_)1Dgmn&bF0k#8YVt+{`9d+lM~^>Drb!7cAeQ!?YOXxf;!G z!w#jhhGMf=oJ6+D7sVOFG99|two~SB-2r^HZpZ$`8kzslpUW+|+S0gAL*e9M+rN-C zAwz>tX9W!X8~FH6uQkpW;^goP&qCG6S?Vr=Cv`QuuYvYuG@V%7f4R**>36>U*B`m; z3vI1oSETsvT0lF0|4yiLY}PaEkln7Avh-YH-5SS)|MRuzX}O!S*Z~doe(ud}S7_pS z%(5B0foRj|N4pN+7Q|_RZF5%Su<8%nZRl{!onrIkefCdouec8#M9mNRh$dqL-e%nB zHom@g*HrDK<8#(oq`4EYS85HW8iF`F_Fhi`d^HsFQKKIh{0#Cj?#0QxapOz|h3nMu zId@wdEb>GUqun8b^X2*^zKeXw_wT+)IWynTyyDwUHU80Pr(Qc*vCPSzS++K`dTR5u zUEk@!X8G1}3D31~M^KPKMQ};t_$mMT&Ecru@`KYp9Ls^wYZ`6v)VVpgRhiMMyiW5S zRCCvzPlRZkfE0XR zuwt|?2N5Ujfd))C@@j(*LQMrYpUfXPFya)V9tAY6Qzn(j%`1QNHSHEwdd>@Wzs6y~qPp@7fw#!sy4X-}kvIaozOMOw6#WU9 zy8^edkv!R5gp6ZXvpp5p13kZFx;YQAaf-^B`^9|YO0Zqp9-TNEe}I zv(A1a)#&)>g+F)T{THfapcVowd)BeRo@sJ~tYXL5_vZ3^M~F?-n*_mC`c_}fWQN^w z@|ds6er&!u903!@!0ze(B$A0Rb=Zr`ckH70@gixvH&>lxir#W7{o;(T%FV0QwIK0+ z+>tK3HjCkXWO*^v(|gujt@i$8AT03N98c0c-?>ZfBW1R?)1;NJzR2_Ckjk+_6?Wqu z81MYerDn~3Z_7Qqcgo@{*l{QM^eJuK_Tuy|YvihoF3Nwq&}QEjDfjBE)vd2tlk;?_ ztC#@rlJn)w!A9Ks$Oh{;N-_}RIkq|_$NeJxII*#{Y0k($+~F|*aX`V*sD1uj^Pkb$ zv~EiNdQQ}AX4k~JW{~7$O;>j?N43*Ad@iAVT8TyNIO&(9{~T$SC!<1fJ*nljsBNw3 z%SwOfkDq2)QhkPdTz_8gv1hog{esC$0RbZe004jkAOyzC>Sut&fdT^n_^<*15dZ77 zGB=>JF?Mov(zh|vcQ9h4rKeMJcXTqgrj;?awsml)b+fj*)||H4;D_%~z2L%s6{LhD z?*5BHP)uwdpFs*)#`9OXdk+wMz0=7xysqGB*yD`o8O0)y;Kcwda1~wJ_6NhH$JWHv z#f9hV`@7VIl_7e7N4^Bfs{%WCXkDshfCVtGkd{Ei|5T(qF9_-7-5PAY%U1vw%HzdZBKOv zTaC0{UI->`Le3L@k;Q-{K)1e7#5)e&uwbe=f&l2lum@)T;z;=(+e}dW4`4?m7$YNR z@%hI)fok3mg;hU$93mUJec`rQ1Y7_T!<8aG_Ni%I*W0{NDT`w^@MUo<*Xndn%dOz&d zXs8tQw9bQdrq*f4o<>mw^LoGW^SRP=-qayMV` zST>9w3^;C_twYet5$W~NXSEZ9fAOFLjf@n`(uss_&%I>x_p9)%(bN3ig--9!Qd1>Q z87!9VeVawJCUr(CaPy zr=e)o`?!i2unZHH6{R$yTPR3(Q_c+r0J$>RTio~Giwd{&ZfRhpm183XC`6<6CdSfU zQdU0OusA3HBZwPZfwRD%?y@$x9_f#;NzaY^NVsu*KTv1Ldu#rQm_OAFifVsy<5NvF z4mI{^MR3&|Ud0tICLI-`!J-aLEy`$>x1zXyQZi5+Zly4Q4?&tnf%Uc%LO9 zF&R5(BiR zJadwmAr9(~*FH4yzBIkW69N`AdU_Di5X0T6BsgF~++pDIZ+FFoWr?W@p={5uukV5r zPOVP2$Ma65s+g)S&nu|x9=mMNuj#DA)+on^D@5zpF3=sHu{Y!Jcl=8*3SO-Cb1+I{ zE3P{Aj=j}>is5GrD%@3Ou5Mdp+pqln+V@@C)b>`vI!f=-zV+e8>S$(SH;MYC6 zXTm>JrG($x3_Xo9R_jebNH3-3l5`3RKt_x?aPhXy52`CmbvsZxGuiTI3!v@OY=0TW zKKfi7iiBJye)H1+004Oy@UF*lVJiVbdw`A|pk8f664C{+5i$}b3eX6%Q1coq58qZ7 zsy9*@(o|1$xrZSxsaQnJtSWXy6r(^(IN1=n0k1Iz2PosV&J~dNvTsmTh{)Xe5ZMGk zzXkhJC`}aKJ8VU14+EYk8~SbTtg-yMqmbqR++9q0?EG!%6y?X zjaeWOJ0dcUSt5~=+1%BSi707;A}ZORbH^&C>Bv|N1XeBPWnu5M`oL#@;=Q{AAFX}1 z+gZqQbzU8{Uc?TQW;}e*=PnM5x;s@A80#!<5(t@6%uqrjYh(qWF^G= zW**3sGT?m3Ax}6|GvR<6Wb&FX94<%j=w;GV4!6W!@X5#cR^p%P)U{!Ye{*V{TF*SQ z6uz?XDIW1V*!CBTP3F!h0+adOiwpRf$reJg7EcX0(LHqO8dm;htMZQmf`y~bQU-c2 zWoYq!-$E4JsDcC3G&=u z#V&V5sD7X*zq1va8F|gn!Dzv=oe-zV7cMv1n1A(tynKWyL2U{$t)0xZjEO`!@p8mX zu^;tLl8_eRD=4QECWcKp9EpExEkKt25Bo~4e2cPTg}Xhh-_(#3+<=CVA=MNjIf6Vf z)#d~b|F*>*X50?{aKf?{QGP}t<`K)^%U_JlWQfbiSiT>(-z8m8!schjWb82Re+Y%Y zNF}K}Ek274jF6>lAp_mhPnmIiG|p_8hzYNzV#Y%MV)&C*DOoIwK# zrv8BlA0oFaeQ83INh@YfilU(TwpjVPdJQ9HPW&h_1dpr%YQNP0y?;pyM}u=DlVtg0 z<_u)66MBny{jEr(O5hWc-ZLg;e@TcqZU60Xt@$OAfDnMKKZnCLKyd_jC>MJTKKzqb zY($l4dR06={UbwJb4Zn`6T)D>(ro2zJAKuuLOMU@= zK(c&N(nQ4tlqrEg2+i0y03c2vh;WlNu)BeiDuZa3pIokigD{o@S#H5ZiJuABn5oM- zod>F+nyUB@AKlb!GWnIu>WId0pcu$kJ)O{?NC7i+KPTSUU>j|%o(I5-WUAvoK-xvP znwG4e#vlg#BOfld9oN?DCmZhh(hu6ah-9L2c>PZh0$)NxY}FyUC|^LT8QRwDg+w~s zHxFc~x~Lz%3B#cw!9+Z|$U>YII_06OCf#sTlTq&Z4;>7}>Kn^tf|57&S4c>+`D}lo zx;C%HSrI`W^7KxC_mthTb46oF84IR526|^QcyK=QYrsxSEP4Y6WrmEHVfF9$_c}Yu zfWt(XC-r(}wCTaDu4V&mxDs!6Fy9eUlwpSf3YLAUH+4H$qUVEY|Ch4IWu1Armqqww7nnFe8se&iwu>H5OnzzQ0y3$%pq;s{^^ zJjV#_Zm31I>Z!46_dxAD(;h9OXYs2qm^|%)fG#iaQcHzY!z2Kq`@`5c3RR_+AzcMC zekDa(O0F&Z7iC6*W*RE6>h~TsG2Jy>Xo{Jkit{+Jy%`UxG!*Dh1Qa=k@xX6GD zxe&SOp8dQ2JH&_EHYsK>e2h?{CeKW|{7}FPg?xTrjSI0`!U?(e3Gt^Y;R3!pQlg~l z-myy(4;XY97@8d+d<=dReMF-bG&(Uo+iv*P%o5AvO(ap{B%G+d;Y5yzhW1n+W)01b zfFrEl(N@((fEwgBq**?7q)Q2YC~QX2CrFxB%Okzl$#JnXenOJT2m7F$GxVIYAh*mwJLV9f(s$QjN1^xsQbbT|f!xgk zP=Q@lBAl|^DWzNiZxHVvHM8&1%jtx|?avdD)sl_XUxV>%@euaC5`NXnhk~n-soSe$ zpDB~Engy%vTI+bL*At5W4pWl-4d08c(I{Bvg*@TSlKT>YBvMRsmCB2>wp*&-!Wv*j z(;lbqWe=QnN2hn?2f%H7vIml_v>ED>2peZ#$yigl+C-0G(~5ZKANzx0^u%sJ9iX$_ zTiQf|&Xj6!qxS6JHXuCbMtb>hlDlO&PG-P5@jWo&D2|43odV7-s;_4Q?32-ZZA|ZgpeB`CH)L z1geqi%|v)MHTo>TJ2Dv);OKFR?9@<3eKkC@jV6pEEGd;jr{|Q1-umci&lkXm=f-cs z2}ga%X!KR9bajpnu@2_dIfrnP2SsG}>;HhbH!kl-CZI!&eK8Y!9><(am-Kl(_&4iH z6aGx4*4E1IJUgi3iS`GE*1FDN?PYoVL4U)+(dchuCO9;2iD4ijyZ^x1j!{uDFV+Pk zafnzUipg;lwmOjqR>+he(}m)0FnuBY-wHa0rDXcrtIf2nJM1ZzcAX{(*Fu97sDaMA za2^k`iXv~W6?^3V;N|d6hVm?x-C()2-Hk_Vb%+mg>oR^HOCf35aa$T0O`15}IsL>9 zowT7tuk}0KZhe%Ty- z?XN*r{CL?+dM-8dI=EexA+(u9d;oY@^6RgP2f#-K)Ov?T8)S43=4bbI;LUd5yHKmT zHnn_eE7hN3)y}&T7rY}EsBJh?xc;2mp~6&20wj6G&`8f+p-ebRW_gm>G$4@h9XXBz zPCm5KrrkJv``&&xj@6^qi%k8j1ive9UrdAEeh#PwH}BYuD7D7C8%z?jkXkq`e?%H& z&-dOg0TABSK+R%^_(4(Vy!vIN@BI7 zJ&x3a_Olap^Tr{1Wj|Au~$%MgqUwNj)**A-%{Y+bjcX#EMa3oJ6D1>LHkTysPq1KY}hG%ufKi)1s--rnuCYOwfeuqF5DmQv5)Fa zG2FRrd1od1kU;g9 z>}mqL4<#`p4p5TcGE-i<=NomNRq~6-N>J;{HKfX$^U(V6isRJ*h0AzV*UuTwG_=yD zho)Il@0rUZ@!8Q4%zD+spN<+DFax~MnTan()W1i;O^0(Pc+7t!ea!zwOfO;pTKR~_7Dj? zKqo(hRN{BPB8&jS9kqvSuCU@0lqj@eBA$^sRx_ZEb2F15KbCCxE`!@9=9q3T_esHq zB3VRq!oAZX+aR9Lx)$7tA%B=6e;}pHD<|&gq+U0^isIjxS=S2xi@F`+<%C7LI_HE5 zxA%+FHB2bU|P3ttjf)Qh^!d0}l7R9><=tI;L`%}{% znRAbQ4rA1cDrO%a7Co7s-}4*>n+KeH18*R@pJaa15TT7K9SR z(99}5%kh6ZhE-k-}K1(1rm8$8cK zt#gRQbw7bBK%oRd74b$7Q8*S3Mt48fpTa0>V!gk@^JTTED2# zG7NqT(YGFYQf*YUodBX%17GAkB#g4#RWG+WyZ#?%qgOmP%hg^*oL+lcXRjg6!V&LH z{i;BRya8a-Aco{*Y#d2Pnk~{RqXUbUID`WYEtR3*QEiM(oSNE+i$={0rp2uDiQVo~ zrFqS6d-=V)t!9xKwTm_y75q&D?wqxvO&jiQ7f-BWnWGkuJN5i2QQh7={{C)nalF{L z+{WD)&}4u<`5)Gp>&)=2Wn5XMGH?U2CM5fLnw?_Mc@de7(9_^ZpHG#Am-H(2-tqQN zU?g0vHf<`RO%k{1w`qQDEFNs@YqfSQu0G`tnV4%bKfnEUnZvbJjvH8Q*|OQu^Sg0cVwg@dVR}3Y+97bH2FPedTbeh&NAPeh*SM(_Ygt+Zld8?|?>_ z$5cPNvDec^6WSQ$!t${mtEY6m@B$8qQ9s3L+&yn9$F(lDwajL}ziY0~{yYMrk+#vv zy)z>3NyXuv*3sd`Rmpxngw<|IA79`BAjucf|1=FawX>6*QJzr)wg-Rc`YbB<{a z?o{G)J(>sKOa+2@B@u1j+jrpXR>obw0oQ`EUXJH*vnt~EwvovZCx0FMJFWz@Z{f>P zJ@j_sDEwxkFBsZZqOU1_$PdxB><gmolG!a(3!Wg=L%FH!Dk_D$dz}_j)G=O#(IPDP)hWptAXBqEW!oR5@v0|3i{P; zXgC2Wrqe?qI`1>X8_&CaO!V(6gRWZH6C%`g20#drQNcEMIgrXc?kI4;=co%zD&Im+ z(4lNHbp{bFYP`XDF?i6hoSW0MJIfq*JSoz8d&V>q$izMcgsWbk0fAm|AKowfWrv(W zwB>k~-Def@kGVwM|Ql(EA z4!0lweX-eVIfY{5EatHZ;`Cu(Oc|^rZot{1k}}2~#DgPA+k#-=2hB^6d46$#A+VlB z|46|pHh|WY#?BZ`Hu;QjndV<;rIk6*{c>BeRPD`8A5bKvtm+NaNXJdZe9e{e)9D&~VER&|1q+>1wHHQ2dn{W%Hn&NZyJ%+2m{pjJCdHPeOvWu4ZIu0?^&SK>x@Ip-#Kxetf8C5L~b{xuofZ3Z_0 zb4?$``S>I6x=;s8CzI7Aaz<5)vQDzTIhb9E8<^YBbS2EMD0F8mrWBIKqxda=Lq~E7 zex&~vyQyWq(M0e>%O^deq~qrnuDP;G1gnRWtsv|2INp(f3N@@QPNOAs#d9!4bkm;n zX11Uo+Swpmf%RusYJ-TPO1u@?n7h_vv@U5kqi^w&+kECPqk#i2}BF@MvC zKHBBMeu}xl2ZI;3dq@fPu;ll$mT(l*VG?JWEb%MxCe#Kka5CgmyXZ5Z{Tp|<_Vo5`R653N0+8zVabJ#jFbidZJ4`Sc_qX| ze-@04EZ(fSbr@Sg=X?BT2jS?*Vt)O-)8?8RzJV3DEf%Bn;=RPx4m8&)WOvZ1yPQux z$$g*>VG{oADx{TiH^0h>hKmZF%d7ky$rFNukK!21fvimYWqV*a^DJ1)NQ(4O)13&R z7>W*!`AJ&U$wdcIg}k`RNKOJ=qdgcW-05*hkP@VQChf^xHZ2+LF(w2Pg&B-jAo9A2;5rm?{L zLBUPn0Q&q1OJ!wMPXh;al2M7`ds~l}DRU}a@TA+~<54$dQ(iV4hzsKT>*b$If|fv#2r%Lz%>2=20I?{F4~H{#8J5G*xBT=|QTUJR z;kENRZ#Yv#=3+z9wj;Fq45_!F7>6L6g5yZplQ8l6Bd_1sUdt2Xk}taUP6Kcy@3r$q z#mE7E3d@6ag0xM4Yf{N^n4J%RXhDd&eV&^-`I?n+&5h#83^nAjK!hmG+4WfXN#tJRo6qGuJqSe4hFt?a?wi58 z;kV;dZVRv=y+<^Q9V2X04|sdDH-0$;sd}&pyznC67sLpI-dQt74E|}JZ*DsaQMkc? zE4$eX2L~dc{E(rQ)w%RPwZ?Nuvn6GPW(wqh$>s{amN1k9?gauC>o44%&wZhl}m@DtSTXfNg z!n|-y_l6$t3OqbozlW;-OcVF^()gwv>xw);S-)$l{dgqs&86^7JXk02t)=iyJ;)^R zEv4k@y}LohNRGw_om@=7<)^ZgP^Ee!8!1u=-=Dpp58KnDP8X`D_$pIpi2YmQLyb9B zRGn8RU_dR&uJ1Oi;MhH8z$cngFOMhBLQaX{y{ObjtSB1KFRVxuR!E}6szE$A!V#%5 ziX5{?!Fo)18$T}&peN_Xh^4~ILzIn~mB0K4Alc4C%{xvCj9ijHCfhAjYE!&c4n2AC zTliYdKmw*b8&i>srO3rX{CX*Fqnw~wNpmUYY@1Htc7?G!5%KS10tIKBk;uf7s=#Sc zSN_os_;F(S!?^zOWW*vlT8Q{E9n}Nor5uFxYKQ>fr_#n8lpIP9gj)a_W)i}mSE!tU zZz#EapP+}DAjx*y&3qnAJ#T9j4f02tx*WAe3+X+=$mcmn^y2GeylA+=o@{| zSI9qXYoM-pfm|bd8NfDWFgA37l}v4yZU+7E)DSj*l=fT$yXw%*?pnvYy5Yx9`63j& zZeta^deI_J9{+oV2sP&1TSL21bS);->C<5 z;MZ&ZtPOu*QvIQHoH;M9I42Kuj5w)lfWmB2IqoY39s^Ku6AeQ|&AxwB?ii{Wfo5K? zl|O0&$p17%)&rFM8Pp=s16x5x_ns9D>yAM6Mc0k7UA!mD6fSeu%AUVr3wLtszvP_I zS$3x$bXWD4c!nNaUD2CM)qcc76?6^X>tS^Uck2+Y)fo>!9C`a4>}p!S*snTj6_|U{ z^*yvh6<*;dcenMIatz*yteIctvo^+@xJ93077`rIAqIZpqDOZhlIHM2`S9!l>Asuz z$m!T1@eY^CM_;{04h81`SHA2P&XodZ>PE8kX^x<6Ic{VK=kQb#7gv8{;ik$Wy$$TN zOn@9N`@ZbV^mtKN=u5lQa|l*DV`p+wu^C9S^$ef2t*Uyo!*CB<7~3K-wu<0+OkU{O zll%XXBxN)(_3 zOkpGgla3hKJaSwGIJ-uLyQ*tx?@pl%Z~u91(6?%x(HC#^>{=Pyy6ab5tc>B&l)^ST z&YO!!ZqBaW5Aqdxs*)z|9DFXn=ifsC2kp+;zVkn{#7@pr?SnSR1MjHd76Szm^}>9B zNq4+8=Jg^>ZHJ@o*t zTjA)N-{FrA=X75QU^AKpDQmk_?qHT-4ze!&^NksU?&v<4?Le`G`715ygG6QG*2<8z zY2nU+=6`I-@jCTKZl#rM`x6Xj+v=cMn&;nldybGsvSh&4h|w?3(1>py>@39#d_4RL zUYiGV@Uh4S9z+<_LK{8@gTD)uW^aje;!b{~^KpA$!c=3TYVe9(g#c`%q~+}wsJi^a zs<;qUL1{LUMI9JvYz5#8ncp|yNVp``CmRLeODKcyiu(9OgTdz2sX{UH7Q3Bl__1EN zDRBAz^?cB~v|2k1#urG)J`8Naxeox0_eZ`daBE)n9c)5Z;k#^-EaX z{Lkg?tE%O=8?&#wA6!_ts7DjWCsT)W$R6~--u7Wzf<>LFd2hq`POuM4%uy`}evz)U zNp;`0X1ML;@;tp$S6TzSQ|G?X_CM-gBtKfg*j6%i zy^&kF%I5ifl3>>X&Au1Xp>bB$A_uPe63*sDZsf-M!VynE%+>TRP=OF?HRU+@A2l}B za7Y$JRl)=6(|H(EE}x!5eV7L7^unv5lEBC27f??=>P`}?`nw6&lR=ccnYopV?_%$H z;&1V}Sh-5Ed*%>eUg=*m)H19?pzeYiaJSNt!J=@rHfXF~INh^eID$hI(?o({amfWf zsPEoU$n**DP(-CTT@&#sK3Fu_@YD0Yd4IDMo10(FEr@y>$1k|Hwj7H>XT<})y~DUR zp(UDYMQXG{h2pG!;jwCskni+csYK6xWi*y7+`g>9V<9nHiBZkonq7Spuh-q9>d<*fvjgzm{zn zMXW?^bw)VEj%=IO+=M*nl=bRZV8GSzrQYWOs8}f5aho+N5snrX0=rmDH7hl@aHiA; zt4(6AqAqa7&(Azx#>{B)01CY-ak$y&1-8P8w4~b8S;Sp7iA8a=5e2_`G+iSYmJ}qo z@^8L`iQKs4-1IW>8GVS%>DZ%pkmCd*xQ9HpwBEb!8>8s-E&^R<0RKd)yrYd*IH6Om~Uc2oKI5ChEF#gQb&E^ct>o3+A zH{CC|Toqogg&IssEYoeGJl(dla_efVnDYJGcl+OrDHWKWHyhZXt|$!xQi6Pt|d zraW{r0R*y)9K=z+_NofcQ;I>;QqL<;ysNlh$P~Ug0$;jGI;XMSv4>Btqf>RC9-*IJc{s@_ z=P}=qW3kg8zz+LCEMM8|j#jX&ju_zXh)YTNV>>hp%2Ze4;;sdCA+5$3codAT7TcHP zA;dg7fp3z$df+G;z(=V$0h0N|VO#(A4)7y0OdN2C54F8w8_~1DYti_tVySKFJ)Y}e z*m%M1soRnlL1V?T%-h~7#00Rb#4qLe4N$lcs{e%Qr}^k)iJncG!L#;X(FoEmb6JC?F`j+LTD|W zOXHxQl`g}0fn#jY(LpIux}8W{r0CcheRrY|?= zv+zAz2eEeLx~d0Cgot(W8kVDNSDOoa%W%9YTBvv5T!ep@ZfN#$}Q8q-uum|Kv_$f2-+IkfhWplN>2PaOeoO)8(Tk z%ach_%x9ZMH@)i&()6SXc-QuILe18@qT%Xa>Ua6k$#Y)bTl(E>taaB!4y7muoh>Ij zs}`Jrs(J+3O!8iWLb&mQ?-+xaZSxfr0jK%}*<1=-^2+o<3Ea^}nqTV3^??QKX|F7= z#DAafRb1L8pjxT;%gj)tmk;^xJyziN$IrQ7rsZlBJ>*zV7iVoiw6bi+-c zxm!9U-!P|cqMr05J?_r$OdV;=8JkC?%GX)5mO@0Z4Tjbdk}NUSri6t}9_mVr5`T(i zefFdb!3_F2FysKipYu!8sUHeFb*pI|jWY@8#!~-PtvE_x@>pI^5-@~(=V>BlM?19-;ZH#CfkAo?mXXDFH=u;qD zNmbVWC|LUq%jyA?L{}s)+2A|5vos9h)Gc+Dk@l`QQrr=>>{J04+4D1;Q6LPAQ+vyv?;-|8lRm7!QT>xlJsl&V$sm)1fR|0n#yK|^= ziB*BzKIJndGRJuxX@)ZczH`Iw9*fFfehGkIrf)egPi2COCMLXuPV<*}vY4RNEk!U; zRwqlJ%0ou+3W(nS^xR4oew}xkk6>#Hr z-<~wb<;@lltjY2r6g&gX=_z(|mUeUgn#p1QD^_xt7BY%XD?7{f{>*mYQ|pbU>L4~6 z?-^(bUS*7UqPDqM9^~SSYW2iU!MU0rk_dq*n&eJ6MP7$UQN1T*^d<|6bTis*~?SG5cRc8B{iobcOU0q`Jp07;#r-H8>>2c~fYMYJWa?s{W_qOrNIjiDCBN#P1)=$$PJ>ux?FBgi2ZV2CsUHO; zXotr}=iOsuj@QC^hCuAqId^3h#G^#ai(dMiU)tsoh^Qg#INKOn?^;<j>mQSIg5M37j-PAq%a>fe8L3^ zA8gdr9RDtT>sR6OXQ4b1m+6u6|AV1VfH7EJ9)~b?J$dH_FJ?|T@9fMF+!hLM^L~TL zt!g^#AWJVSV$9YLg0H4XLX;&bbYT#i3jz#>5U|bx^@Y34`m_xcv>mMq+6CpSatU`J z)Q03co(y^GK5$#K0~EoDJ0gG`#Abp^+WA=M+Wzk!-0-&oQDCMC{>XFU^AIS-W}!0pSVBsWLkrXWxWAh6Eos;JcIXPFK)cT{Rc zk0r^6q=P6Rq3x(UtvX(kyH;o;-?kz`QMvPHxE%^|&e)VYWLh%FIp};Y<+B;J6>O$*>>tg3=h4o#r6?Z3np7DAi_ImCwrmp1S^0?@_t~U)g^r0PX3-_=1!*!1UDD8iLqyJsy-d~R(IxZ+PxD)- z5A;lb|Nh-h7%JHxg)ZZjz_uZpRrKko0{*OzPb18M$AoKKF*IfDJ3(C$l(MiiTE@2} z-~YB4Lshq)g2LJjKg1)k`dB5XdhZegA&snqlpwOlIC#@3GZ6PFAedRbr(&fw5kj~K zx!B=2c`3-5-_`*(VGULoozv(Lj|Umk=Sd3Ir+~F4o!VzPqCk-Ks-Kc6;T~Kqu-zMT zjbLTW{MOa`Tb-;xzHD=fQLvSU#`eQt7f~#I=m{;EW;sS8@`zD{Skr6=-IlkK%^trFnI6{aXvZ!>4~0K&^R(8`5Co(fH`A+AQ)VVPUANB>*8O@DNV{f;DJptzqyal! zBaVVC3;a|1MDai9I;U7sdWMZ|+qP{RXWO=I+qP}nwr$(Cb++}N_xj79v`O1ZnqG9K z7t?1gnu_$JEoCQf))VrR;Np~)=wbxX6oP!JWJ=N+X$^sn{aRs)e<%Q3Gt+9tnFOK} zP_2tU%Lbvz>aslJh@8a8R6L>acR>DPlQ$%f!qTPUcn(xLkO`X-Dpj@$71iPSBv+Vh zYd`*9EF}w-gdQ(qB!$J4=}Q1{uru(!u%(nS6bK^RrIScae57}Hn>v5Oni9!T_p8Ak zu9)_9Nhf4@jD+W3?7cOPLpIgk8%e+z9v2be^Tc~oTDI)e^dZ8*mkBI6^64NU$^&^wB`1$%BYEWO0G0uZ^9Tq#&NXB@b&5mBb0__ikS%wL#hA`~`GG#kx48|0 zKgdaANI@7+p3AN$0dMH-HoKdKHnDFIkrnnf;=V`-N;Sbtc7zX)f4?fbYXCfN2 zUn~I-b=G#JKvj)9lxRDmm>KPQ8^IG_z9fC*b&f6rPdDTyn@w>^@)(*m$o2Rw6*oqE z+InhQORE)ybYz=cI(Dy=jR{K?VN2%0bY>%C4@q*4Nzg#H1=VYRYlL!G@)!jM2D-fm%0>>%NOt83*TE+ka*$VKLiu6WVlrm6GqsltdWL*_t+{qvm2SeRzZf zGKxtY=wBprV!Ib?h2!yNog8oB$OE~P?UQTz%jun=&;$oCT`P_uG`-@GZGam4+v-Y2 zM@=_yi#H5-{p1)(j=$QNM~F{&K(V6RWnXhf@Hq=%y6+}>A92O2SFpE1Vm}1n7QU?& zoh?Z20KW-8Xvp4L=NxGYeT>e}{D_4#r1z15IET&)(;k|qCwXO>-Nr9gyGo0nlCsj_ ziKBO^;&%UXM#x&R;G4Bj9ds1r+sg_C$xZ9y_C3W-(EJHgFJ%Wh&kKMHAm|ZKl?Bz~ znt9z9-x}LRh=TQ%zi3sV+zp4nI1!eyZ(w;b_5~^3`da7{*)+~Kh#X99cJ6d=)n2qF zHTih@1X48R<;~6}wA<&>2PVwt+R&aS!2=sV=ZZ%_I465xxjK;EmN{}g2Quf-hQK?< z3!+0H_2JMurT=XRU&%oCMlR!+!8N7+O42@6h9{un!Rt$mcy~OIGpkNmm9C+pbb~L5 zJgSmD&emAzl(5>@!~h=9^7aF&3ura|!oTlBAwg_m>xtjv9%4#zgD(KKYa0t}6%bxs z5bL)}FivL?FQuWMEgNwayT1eWP9<-v}Vwvvr4i@_ufJy6T3 zWspdL%>{iGYHIQ#lxR!(Vl+MfDoA6Xquc}7e+WYZcK`xS9{slOD-K8jvJ%bVk)Cxw zf`{?(iH+V92Hh+R-8}0Nfe6057AoI$uFX?d=KdJ7@Xd!*b=IGOInpJ!HXlkD%RUUe zh$?UCjgB(GDk`QKS--Upsiv};(xRY$Pm_+0LA1kSh@y0uD_NJ7M%_`+jebdQb1;MG zhE3_0?-%tK&}4Oz%{f7 zo>6EQnh~}0+|jWxHjt7cmIek1atBnJO&KHwCWL4DA+7VTBwo+#Oejz}+dr??$c|%H zw_|Z1%gT)bq!$Lgn7t!J8uZYCI92)iQTaUeu^zPWK-I9l=$WtpvUReOho*b}5 z0IM!KhKxf%3oRi7ti)tLst#c8@XEk9q{dbi^`$Nb=gXzz1)nYfNIexuapDS5c7}tE zG$Pl%I5{>l3xnlDn%Uef=1surH^xmE&SQDJ zS>-pf;|-E-%^xHbuY~k0AYYRtEY$PA5A=bs6YO*z{zJf*Cq@iPbF7vt0GW9%LP46x z%lY!X3ecPE++Zy!axqzdjJ?)_mLF8FE% z0Z=Kmht=%17xSnOKM&&a0sp18&gKc*QRck!HJa%>jx7_vlGDB@I0c`1duw^xP^;P5F!9y&%dFdtdBx5wER8Iu&C=RpV$hdfSs zEaJi#Z?%Q>k?=%AP?UM2-!;*YoMKiSA{%&suL+dU#iOY^6392HhC1!%TnMGROkxxl zwJ6{be%knI0d~SRFbSlWcOKttVFV{(ggBV@XqnMxojvd?n{YJDUK7>nCK|eQgLOK` zrv|l;z&38?ioH@Nrm~)QCv*VkxW)JGPjK?*?q86?jkIgbp>|Ic*K+WozN*>t+|wV} z%brHSeQ(&?PnRkB0=tfTbNxamu9WNWcU@TMv?wWZP5jdtKpX=2vD9dMEVB%8wW*V^ z*r-PE_j%{{-TzcqqIl^F8-62DQ;qC-n7|l;hMOcGl4>ntVE4-zUh*Rk+!pjIw z@mCP4`eGqjE8sOc~ExJpvc?e^MLeNzB%fYK;FK7xtw8YHI0qL%mLWFmrZ!*@iz zv1(;Z;4Zq5=VpmWm6U-R<{sXE0o}q3*Vvo`?a9Iq$cuG&gdv_BVPjEX5k9;OkDy6G{o%>%LymQJUIj4CyWm;O61Bs zsfIEn*Ox?Cah85ZVc3G6P!@@q5*)EjpPOL<2Sjf%8qNRklMF3d$Raw$8pfiUnN*X^ zXvS$gkx-wQK7%x(iKhxQ1|H)h-bXoQIn4F<0wa6YKyf*^3BJYq(1^l?K%@p)M1hFy zisU`bk6m|(tL9~`NXb0IfHcuvaIWgTO+=9rLaDocmT+|F zw1*-1OI{cEZ!JXFB9+7%bEX{FK&Azd84)DiOh#{^14l0w`~ka&GH8R0K53$dneq`; zX1vlJFJ!wrEgG*S{N&R<{FL(#9=$`g4+8xJ@uq82N<_>_{L3}sXoYEel`Oy>6`96% z^!J}GTQ`uE{pj6}+i+Q}9xNj!Ju#e+-I{t9zcC-?HehbS){TJH3P^b<)NH=`ArlyqkYYz%FUVmH;y*lLPCu5r$ z&okn-ZbV1V;d2Q<<5c5xYA?#4Lk-owFosd%+09Uc(S<5To^z;pbJ&?v$({GlpI^iu z-}~ROuO8C=y&}M$-IFJ^!+YDbu5tB0Vx+L4!Sn+8V){p@(XeUkbYTHGpA0#H2M4e7{JW+l<);bTw6Yw6Wk*uY{@u607qp745HZ$M+FZuBv(9cN&jFFsARb7cr@i>??>x!jU?$)D2+4N>*ZN)ds)=I!_9#Q=t6+E=A=d1QANXNT z%Z4$va~TECvoXusN;E>9DX3ePF)PIeL(UgIGFq2+NK}-~HZ-i{fp1BtUIVOSA?JGr zYR^|;=K+L-(ZcCQ8aX@LNFAIaS$#bc^1 zO<4z<8JYoUNut)MoM-eow&YE}?81B1sPF73bwGhcSO2Y(x?iDvL#t2}$G%P8?!0^t ziHt#0&Fpz{Z~w!wR#@-11A6Xjaers`-KD$!IoFnryP|{5EAo4c_)n%)lUn0H!aKME zjOL(pzdo~68d|FK_Kv2#eIMwWtS>ImHRvPq@Fz*$gKT;A+32<}az*wM;sOG?tl%l; znt%A^TU!MMqQ>AB)?JBH;?#IHNr7gXO#fW!B|vZ`<(c40XQ^eys>@0=v$FPx1N`}{ zzQfEz()~4UZ3BI<*&x+r>>xziTreck33JoqJ)k}Cqz_;iU`~kAvPGygPRXAE{rE$< zA7;28>*2jr<=9_rS*K~khH;0NzJeohnXFR2lKmNQP4aAyMlruk4M#n|6Gw(Q?`y&*^p--Xbpv_34^ zQ?7tpsEQPBIvbn|0L6<<7;J0P6* zwnv#xi~ved`V(sglSI3h8861l_Tqbvy)&T(X4JX%C;Nm8#<(<^_=~Rd58dYoXnkG2 zgj50WQ~OXpwr{K9-_FubWXGyk*}h0&yMg!5flHL&KWe%}T2CvmjV^L7RZAeoa!H_J z{~_&UHtO6im!@<-pkQ`jl&eWG=^fX&LVJ3V9=^Fe ze@1XN{$v`CxnC2Q8je;(Jf!kaGq($}P6at6d}mn3=C^p9@_U+D`U}BOy7`L#?g(i@ z&3hu`j!k^9HWqa}mCsI*aIo)jV5LEx=xeavb8xMJ7#-3eBq{+T-#Ej7IWnjPfEoBu z#FKx0xOS|tp4D@ux}#(R#)TJ4hW8uvPsR_lFcWfo%?_?71|PZ--N#LfDO(l;p-w z5_JIN(4xgm{JmF)3blj`mD#;YW0?z;(PbP{wCJ`AVE8^`bcEA@l%UX|?l{Hyn={V1 z$IdVCbWT6ThJqypU zG>p&IR%4qlPnanW?);hsYym=E15-5BqFwV zVJFM@Ym)WDZ4@{$^WRBIrs5<$8U*-EGESAj)-qAKs-P;sB=bj*`WK!jQ$JS20xxO1 zMKt>OvXXuVZ_fU~h`S&T{yd&+`~?``YIuB;Pq8rCy_llOP=xbEC!uR7A(j%!O$>
    06?;u0I*e(lQa!t+}aLIt)=trbpLrkOR= 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 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg.meta deleted file mode 100644 index f17c9863bed..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/System.Memory.4.5.3.nupkg.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 3b6419b3ddd8e3c59a084fbccd38354b -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT deleted file mode 100644 index 207a2a734ad..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT +++ /dev/null @@ -1,309 +0,0 @@ -.NET Core uses third-party libraries or other resources that may be -distributed under licenses different than the .NET Core software. - -In the event that we accidentally failed to list a required notice, please -bring it to our attention. Post an issue or email us: - - dotnet@microsoft.com - -The attached notices are provided for information only. - -License notice for Slicing-by-8 -------------------------------- - -http://sourceforge.net/projects/slicing-by-8/ - -Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved - - -This software program is licensed subject to the BSD License, available at -http://www.opensource.org/licenses/bsd-license.html. - - -License notice for Unicode data -------------------------------- - -http://www.unicode.org/copyright.html#License - -Copyright © 1991-2017 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that either -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, or -(b) this copyright and permission notice appear in associated -Documentation. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -License notice for Zlib ------------------------ - -https://github.com/madler/zlib -http://zlib.net/zlib_license.html - -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.11, January 15th, 2017 - - Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -*/ - -License notice for Mono -------------------------------- - -http://www.mono-project.com/docs/about-mono/ - -Copyright (c) .NET Foundation Contributors - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the Software), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -License notice for International Organization for Standardization ------------------------------------------------------------------ - -Portions (C) International Organization for Standardization 1986: - Permission to copy in any form is granted for use with - conforming SGML systems and applications as defined in - ISO 8879, provided this notice is included in all copies. - -License notice for Intel ------------------------- - -"Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -License notice for Xamarin and Novell -------------------------------------- - -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Copyright (c) 2011 Novell, Inc (http://www.novell.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Third party notice for W3C --------------------------- - -"W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE -Status: This license takes effect 13 May, 2015. -This work is being provided by the copyright holders under the following license. -License -By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions. -Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the work or portions thereof, including modifications: -The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. -Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software and Document Short Notice should be included. -Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived from [title and URI of the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)." -Disclaimers -THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. -COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT. -The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission. Title to copyright in this work will at all times remain with copyright holders." - -License notice for Bit Twiddling Hacks --------------------------------------- - -Bit Twiddling Hacks - -By Sean Eron Anderson -seander@cs.stanford.edu - -Individually, the code snippets here are in the public domain (unless otherwise -noted) — feel free to use them however you please. The aggregate collection and -descriptions are © 1997-2005 Sean Eron Anderson. The code and descriptions are -distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY and -without even the implied warranty of merchantability or fitness for a particular -purpose. - -License notice for Brotli --------------------------------------- - -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -compress_fragment.c: -Copyright (c) 2011, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -decode_fuzzer.c: -Copyright (c) 2015 The Chromium Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." - diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT.meta deleted file mode 100644 index 6e0890522ad..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/THIRD-PARTY-NOTICES.TXT.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b3fe6450b2adebdadb6f022c600c54ae -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib.meta deleted file mode 100644 index e9b452b3e60..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: db995c57b21d2a886862da3e375894a2 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0.meta deleted file mode 100644 index fd6c8e2d6ab..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 6f9f81377355dade297ceb76b84bab10 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll deleted file mode 100644 index bdfc501e9647719549793297acb072d33067d4e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148760 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 IXGb{$00BiQzyJUM diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll.meta deleted file mode 100644 index 7e3cbb61986..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: 30a29d5b265da523ca20d43a264e7877 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml deleted file mode 100644 index de9af8989be..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml +++ /dev/null @@ -1,355 +0,0 @@ - - - System.Memory - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml.meta deleted file mode 100644 index aecf5eac9f7..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/lib/netstandard2.0/System.Memory.xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 3a1527b0a64676fe88542f420811e1c6 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt.meta deleted file mode 100644 index f52950d847e..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/useSharedDesignerContext.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 245d848d2e32c738eaabe264d570fa28 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt deleted file mode 100644 index 84098337995..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt +++ /dev/null @@ -1 +0,0 @@ -c6cf790234e063b855fcdb50f3fb1b3cfac73275 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt.meta deleted file mode 100644 index 805c58fd0ca..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Memory.4.5.3/version.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: f8033dc14c362de7abb5c1d4ba82377b -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2.meta deleted file mode 100644 index 597fb58dfa1..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 28121a23158a08fd099fee07651b6fe5 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT deleted file mode 100644 index fa3121dfaf7..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT +++ /dev/null @@ -1,23 +0,0 @@ -The MIT License (MIT) - -Copyright (c) .NET Foundation and Contributors - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT.meta deleted file mode 100644 index 3e33a2ffd85..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/LICENSE.TXT.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: a9abbe1e2cf90e99cb3200e0e16d127b -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg deleted file mode 100644 index 4f464e12ed6889d99bc849a269dd8a3f547a81f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104723 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

    dKP05&Bo2xtTrg9PEq4=FVF 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 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg.meta deleted file mode 100644 index e670a731ae0..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/System.Runtime.CompilerServices.Unsafe.4.5.2.nupkg.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: a0592ab03350126988dc73996196f102 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT deleted file mode 100644 index 207a2a734ad..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT +++ /dev/null @@ -1,309 +0,0 @@ -.NET Core uses third-party libraries or other resources that may be -distributed under licenses different than the .NET Core software. - -In the event that we accidentally failed to list a required notice, please -bring it to our attention. Post an issue or email us: - - dotnet@microsoft.com - -The attached notices are provided for information only. - -License notice for Slicing-by-8 -------------------------------- - -http://sourceforge.net/projects/slicing-by-8/ - -Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved - - -This software program is licensed subject to the BSD License, available at -http://www.opensource.org/licenses/bsd-license.html. - - -License notice for Unicode data -------------------------------- - -http://www.unicode.org/copyright.html#License - -Copyright © 1991-2017 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that either -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, or -(b) this copyright and permission notice appear in associated -Documentation. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -License notice for Zlib ------------------------ - -https://github.com/madler/zlib -http://zlib.net/zlib_license.html - -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.11, January 15th, 2017 - - Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -*/ - -License notice for Mono -------------------------------- - -http://www.mono-project.com/docs/about-mono/ - -Copyright (c) .NET Foundation Contributors - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the Software), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -License notice for International Organization for Standardization ------------------------------------------------------------------ - -Portions (C) International Organization for Standardization 1986: - Permission to copy in any form is granted for use with - conforming SGML systems and applications as defined in - ISO 8879, provided this notice is included in all copies. - -License notice for Intel ------------------------- - -"Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -License notice for Xamarin and Novell -------------------------------------- - -Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Copyright (c) 2011 Novell, Inc (http://www.novell.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Third party notice for W3C --------------------------- - -"W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE -Status: This license takes effect 13 May, 2015. -This work is being provided by the copyright holders under the following license. -License -By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions. -Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the work or portions thereof, including modifications: -The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. -Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software and Document Short Notice should be included. -Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived from [title and URI of the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)." -Disclaimers -THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. -COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT. -The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission. Title to copyright in this work will at all times remain with copyright holders." - -License notice for Bit Twiddling Hacks --------------------------------------- - -Bit Twiddling Hacks - -By Sean Eron Anderson -seander@cs.stanford.edu - -Individually, the code snippets here are in the public domain (unless otherwise -noted) — feel free to use them however you please. The aggregate collection and -descriptions are © 1997-2005 Sean Eron Anderson. The code and descriptions are -distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY and -without even the implied warranty of merchantability or fitness for a particular -purpose. - -License notice for Brotli --------------------------------------- - -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -compress_fragment.c: -Copyright (c) 2011, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -decode_fuzzer.c: -Copyright (c) 2015 The Chromium Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." - diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT.meta deleted file mode 100644 index 23ab378274a..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/THIRD-PARTY-NOTICES.TXT.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: ad2aa0f35903c91a3a6f4e68038686d5 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib.meta deleted file mode 100644 index 5ce5490008e..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b36206566e8c87fb0a48d58bcbeeac35 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0.meta deleted file mode 100644 index 03338124f98..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 00b4ff731ea89be429d779a12bfcc2e1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll deleted file mode 100644 index 3156239266db9cceede249731f00c3822e479a1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23600 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 OyIXQg_#$)@0sTLk9O=pc diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll.meta deleted file mode 100644 index b1136d6d6bc..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: c302643d7365a215dacc6f0fe5cdfd88 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml deleted file mode 100644 index 84c02132f37..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml +++ /dev/null @@ -1,200 +0,0 @@ - - - System.Runtime.CompilerServices.Unsafe - - - -

    Contains generic, low-level functionality for manipulating pointers. - - - Adds an element offset to the given reference. - The reference to add the offset to. - The offset to add. - The type of reference. - A new reference that reflects the addition of offset to pointer. - - - Adds an element offset to the given reference. - The reference to add the offset to. - The offset to add. - The type of reference. - A new reference that reflects the addition of offset to pointer. - - - Adds a byte offset to the given reference. - The reference to add the offset to. - The offset to add. - The type of reference. - A new reference that reflects the addition of byte offset to pointer. - - - Determines whether the specified references point to the same location. - The first reference to compare. - The second reference to compare. - The type of reference. - true if left and right point to the same location; otherwise, false. - - - Casts the given object to the specified type. - The object to cast. - The type which the object will be cast to. - The original object, casted to the given type. - - - Reinterprets the given reference as a reference to a value of type TTo. - The reference to reinterpret. - The type of reference to reinterpret.. - The desired type of the reference. - A reference to a value of type TTo. - - - Returns a pointer to the given by-ref parameter. - The object whose pointer is obtained. - The type of object. - A pointer to the given value. - - - Reinterprets the given location as a reference to a value of type T. - The location of the value to reference. - The type of the interpreted location. - A reference to a value of type T. - - - Determines the byte offset from origin to target from the given references. - The reference to origin. - The reference to target. - The type of reference. - Byte offset from origin to target i.e. target - origin. - - - Copies a value of type T to the given location. - The location to copy to. - A reference to the value to copy. - The type of value to copy. - - - Copies a value of type T to the given location. - The location to copy to. - A pointer to the value to copy. - The type of value to copy. - - - Copies bytes from the source address to the destination address. - The destination address to copy to. - The source address to copy from. - The number of bytes to copy. - - - Copies bytes from the source address to the destination address. - The destination address to copy to. - The source address to copy from. - The number of bytes to copy. - - - Copies bytes from the source address to the destination address -without assuming architecture dependent alignment of the addresses. - The destination address to copy to. - The source address to copy from. - The number of bytes to copy. - - - Copies bytes from the source address to the destination address -without assuming architecture dependent alignment of the addresses. - The destination address to copy to. - The source address to copy from. - The number of bytes to copy. - - - Initializes a block of memory at the given location with a given initial value. - The address of the start of the memory block to initialize. - The value to initialize the block to. - The number of bytes to initialize. - - - Initializes a block of memory at the given location with a given initial value. - The address of the start of the memory block to initialize. - The value to initialize the block to. - The number of bytes to initialize. - - - Initializes a block of memory at the given location with a given initial value -without assuming architecture dependent alignment of the address. - The address of the start of the memory block to initialize. - The value to initialize the block to. - The number of bytes to initialize. - - - Initializes a block of memory at the given location with a given initial value -without assuming architecture dependent alignment of the address. - The address of the start of the memory block to initialize. - The value to initialize the block to. - The number of bytes to initialize. - - - Reads a value of type T from the given location. - The location to read from. - The type to read. - An object of type T read from the given location. - - - Reads a value of type T from the given location -without assuming architecture dependent alignment of the addresses. - The location to read from. - The type to read. - An object of type T read from the given location. - - - Reads a value of type T from the given location -without assuming architecture dependent alignment of the addresses. - The location to read from. - The type to read. - An object of type T read from the given location. - - - Returns the size of an object of the given type parameter. - The type of object whose size is retrieved. - The size of an object of type T. - - - Subtracts an element offset from the given reference. - The reference to subtract the offset from. - The offset to subtract. - The type of reference. - A new reference that reflects the subraction of offset from pointer. - - - Subtracts an element offset from the given reference. - The reference to subtract the offset from. - The offset to subtract. - The type of reference. - A new reference that reflects the subraction of offset from pointer. - - - Subtracts a byte offset from the given reference. - The reference to subtract the offset from. - - The type of reference. - A new reference that reflects the subraction of byte offset from pointer. - - - Writes a value of type T to the given location. - The location to write to. - The value to write. - The type of value to write. - - - Writes a value of type T to the given location -without assuming architecture dependent alignment of the addresses. - The location to write to. - The value to write. - The type of value to write. - - - Writes a value of type T to the given location -without assuming architecture dependent alignment of the addresses. - The location to write to. - The value to write. - The type of value to write. - - - \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml.meta deleted file mode 100644 index c4a83ad00a4..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 9ba4a7a6f2232e96a98073f2e8c1c795 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt.meta deleted file mode 100644 index 11818647baf..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/useSharedDesignerContext.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 53d0e173bdb86477ebe32b6d0f5e588c -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt deleted file mode 100644 index 7558087f901..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt +++ /dev/null @@ -1 +0,0 @@ -02b11eeee1fbc5f3ef43a1452fe07efd25fa1715 diff --git a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt.meta b/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt.meta deleted file mode 100644 index 8b9257927a0..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Packages/System.Runtime.CompilerServices.Unsafe.4.5.2/version.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 07e253f0e146e6c43a6ec6b0b58212ce -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts.meta deleted file mode 100644 index 8b5f71efd3d..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 10dd1ca43de00b578b7a58913a7330cf -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta deleted file mode 100644 index d45f1177c1d..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b5f921925c3e131a881439e1ae3278cb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs.meta deleted file mode 100644 index 2023804f8e7..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7f4de68bfb39d5d4b8145d97dffde8c9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs.meta deleted file mode 100644 index d0b7169a59d..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 22f2002d28671854b9e0e1f263d3fcb8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs.meta deleted file mode 100644 index a95aebaeeee..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 2ec50a3dcb5beb66e8728d6649ac3065 -timeCreated: 1658252769 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs.meta deleted file mode 100644 index ab8e8b81237..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/IDatabaseTable.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7f969825278c8e3fd9014e02b825f7ac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs.meta deleted file mode 100644 index 9ece25fbd72..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Identity.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 924c91782f80dffba9114a596343ef14 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs.meta deleted file mode 100644 index cc9f8c5c528..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: afbc59781ed95141abe2453be650b4bf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs.meta deleted file mode 100644 index 1468cea91cd..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5024d17b7a44a11458d975cb1e9913a7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs.meta deleted file mode 100644 index a3953c5199a..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e821d7739e1cf0f408fe82f799c934cd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS.meta deleted file mode 100644 index e863bcf9152..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: c8d7d4943ee54be3abeac55aa74718e6 -timeCreated: 1677030685 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs.meta deleted file mode 100644 index 5c2a0f8e14b..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 2aa159e7cb07436a9997df464c908be2 -timeCreated: 1677030697 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs.meta deleted file mode 100644 index e80a032b531..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e726bf2bab07b0fca9c5affebb1dd39d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs.meta deleted file mode 100644 index 18b3c1e5e30..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c25f637015fec0d56843e6450fb0216f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs deleted file mode 100644 index 316a9869776..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace SpacetimeDB -{ - public partial class Reducer - { - } - - public partial class ReducerEvent - { - } -} \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta deleted file mode 100644 index 47e935379be..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Stubs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3c5f8f3b1a67eaf268e00840da8aa4be -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs.meta deleted file mode 100644 index 23a54bdf401..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e446381d1ca09c249ba226d1e6edbfc8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs.meta deleted file mode 100644 index afff70f5a2a..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 0e36b7f4e40f850758fc453d53de0fbc -timeCreated: 1656515225 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json.meta deleted file mode 100644 index fec54b6bf03..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: de6efa325d604424a3669ae63df7570a -timeCreated: 1678986584 \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs.meta deleted file mode 100644 index 968f4566f0f..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aabe537e4e1a029c8a000f7c897a6c86 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs.meta deleted file mode 100644 index a001105360e..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6ae97cb73962d92e5950bf5185a58867 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs.meta deleted file mode 100644 index 87167287bc4..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: eb3caa783c4812721a44bf70b400f1f3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs.meta deleted file mode 100644 index f54a3c0bbc8..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8ddeb872a1a67e356a06833ee11f999e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs.meta deleted file mode 100644 index bdbd6f229ec..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 12d996a60ab2e81e485ec27d7573f88d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs.meta deleted file mode 100644 index 458e7e19da4..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 45776400b00fadb8b987dcf21080d569 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs.meta b/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs.meta deleted file mode 100644 index 4e0539069d5..00000000000 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f7b5f73c03cf8e9f8b7a37eb90a581bc -timeCreated: 1678986597 \ No newline at end of file diff --git a/sdks/csharp/Packages/manifest.json b/sdks/csharp/Packages/manifest.json deleted file mode 100644 index 137e47eada5..00000000000 --- a/sdks/csharp/Packages/manifest.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "dependencies": { - "com.unity.collab-proxy": "1.15.4", - "com.unity.ide.rider": "2.0.7", - "com.unity.ide.visualstudio": "2.0.12", - "com.unity.ide.vscode": "1.2.4", - "com.unity.render-pipelines.universal": "10.7.0", - "com.unity.test-framework": "1.1.29", - "com.unity.textmeshpro": "3.0.6", - "com.unity.timeline": "1.4.8", - "com.unity.ugui": "1.0.0", - "com.unity.modules.ai": "1.0.0", - "com.unity.modules.androidjni": "1.0.0", - "com.unity.modules.animation": "1.0.0", - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.cloth": "1.0.0", - "com.unity.modules.director": "1.0.0", - "com.unity.modules.imageconversion": "1.0.0", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.particlesystem": "1.0.0", - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.physics2d": "1.0.0", - "com.unity.modules.screencapture": "1.0.0", - "com.unity.modules.terrain": "1.0.0", - "com.unity.modules.terrainphysics": "1.0.0", - "com.unity.modules.tilemap": "1.0.0", - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.uielements": "1.0.0", - "com.unity.modules.umbra": "1.0.0", - "com.unity.modules.unityanalytics": "1.0.0", - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.unitywebrequestassetbundle": "1.0.0", - "com.unity.modules.unitywebrequestaudio": "1.0.0", - "com.unity.modules.unitywebrequesttexture": "1.0.0", - "com.unity.modules.unitywebrequestwww": "1.0.0", - "com.unity.modules.vehicles": "1.0.0", - "com.unity.modules.video": "1.0.0", - "com.unity.modules.vr": "1.0.0", - "com.unity.modules.wind": "1.0.0", - "com.unity.modules.xr": "1.0.0" - } -} diff --git a/sdks/csharp/Packages/packages-lock.json b/sdks/csharp/Packages/packages-lock.json deleted file mode 100644 index 984ab05e058..00000000000 --- a/sdks/csharp/Packages/packages-lock.json +++ /dev/null @@ -1,403 +0,0 @@ -{ - "dependencies": { - "com.unity.collab-proxy": { - "version": "1.15.4", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.nuget.newtonsoft-json": "2.0.0", - "com.unity.services.core": "1.0.1" - }, - "url": "https://packages.unity.com" - }, - "com.unity.ext.nunit": { - "version": "1.0.6", - "depth": 1, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.ide.rider": { - "version": "2.0.7", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.test-framework": "1.1.1" - }, - "url": "https://packages.unity.com" - }, - "com.unity.ide.visualstudio": { - "version": "2.0.12", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.test-framework": "1.1.9" - }, - "url": "https://packages.unity.com" - }, - "com.unity.ide.vscode": { - "version": "1.2.4", - "depth": 0, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.mathematics": { - "version": "1.1.0", - "depth": 1, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.nuget.newtonsoft-json": { - "version": "2.0.0", - "depth": 1, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.render-pipelines.core": { - "version": "10.7.0", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.ugui": "1.0.0", - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0" - }, - "url": "https://packages.unity.com" - }, - "com.unity.render-pipelines.universal": { - "version": "10.7.0", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.mathematics": "1.1.0", - "com.unity.render-pipelines.core": "10.7.0", - "com.unity.shadergraph": "10.7.0" - }, - "url": "https://packages.unity.com" - }, - "com.unity.searcher": { - "version": "4.3.2", - "depth": 2, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.services.core": { - "version": "1.0.1", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0" - }, - "url": "https://packages.unity.com" - }, - "com.unity.shadergraph": { - "version": "10.7.0", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.render-pipelines.core": "10.7.0", - "com.unity.searcher": "4.3.2" - }, - "url": "https://packages.unity.com" - }, - "com.unity.test-framework": { - "version": "1.1.29", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.ext.nunit": "1.0.6", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0" - }, - "url": "https://packages.unity.com" - }, - "com.unity.textmeshpro": { - "version": "3.0.6", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.ugui": "1.0.0" - }, - "url": "https://packages.unity.com" - }, - "com.unity.timeline": { - "version": "1.4.8", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.modules.director": "1.0.0", - "com.unity.modules.animation": "1.0.0", - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.particlesystem": "1.0.0" - }, - "url": "https://packages.unity.com" - }, - "com.unity.ugui": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.imgui": "1.0.0" - } - }, - "com.unity.modules.ai": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.androidjni": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.animation": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.assetbundle": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.audio": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.cloth": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.physics": "1.0.0" - } - }, - "com.unity.modules.director": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.animation": "1.0.0" - } - }, - "com.unity.modules.imageconversion": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.imgui": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.jsonserialize": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.particlesystem": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.physics": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.physics2d": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.screencapture": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.imageconversion": "1.0.0" - } - }, - "com.unity.modules.subsystems": { - "version": "1.0.0", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.modules.jsonserialize": "1.0.0" - } - }, - "com.unity.modules.terrain": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.terrainphysics": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.terrain": "1.0.0" - } - }, - "com.unity.modules.tilemap": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.physics2d": "1.0.0" - } - }, - "com.unity.modules.ui": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.uielements": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.uielementsnative": "1.0.0" - } - }, - "com.unity.modules.uielementsnative": { - "version": "1.0.0", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0" - } - }, - "com.unity.modules.umbra": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.unityanalytics": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0" - } - }, - "com.unity.modules.unitywebrequest": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.unitywebrequestassetbundle": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.unitywebrequest": "1.0.0" - } - }, - "com.unity.modules.unitywebrequestaudio": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.audio": "1.0.0" - } - }, - "com.unity.modules.unitywebrequesttexture": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.imageconversion": "1.0.0" - } - }, - "com.unity.modules.unitywebrequestwww": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.unitywebrequestassetbundle": "1.0.0", - "com.unity.modules.unitywebrequestaudio": "1.0.0", - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.imageconversion": "1.0.0" - } - }, - "com.unity.modules.vehicles": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.physics": "1.0.0" - } - }, - "com.unity.modules.video": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.unitywebrequest": "1.0.0" - } - }, - "com.unity.modules.vr": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.xr": "1.0.0" - } - }, - "com.unity.modules.wind": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.xr": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.subsystems": "1.0.0" - } - } - } -} diff --git a/sdks/csharp/ProjectSettings/AudioManager.asset b/sdks/csharp/ProjectSettings/AudioManager.asset deleted file mode 100644 index 27287fec5f4..00000000000 --- a/sdks/csharp/ProjectSettings/AudioManager.asset +++ /dev/null @@ -1,19 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!11 &1 -AudioManager: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Volume: 1 - Rolloff Scale: 1 - Doppler Factor: 1 - Default Speaker Mode: 2 - m_SampleRate: 0 - m_DSPBufferSize: 1024 - m_VirtualVoiceCount: 512 - m_RealVoiceCount: 32 - m_SpatializerPlugin: - m_AmbisonicDecoderPlugin: - m_DisableAudio: 0 - m_VirtualizeEffects: 1 - m_RequestedDSPBufferSize: 0 diff --git a/sdks/csharp/ProjectSettings/ClusterInputManager.asset b/sdks/csharp/ProjectSettings/ClusterInputManager.asset deleted file mode 100644 index e7886b266a0..00000000000 --- a/sdks/csharp/ProjectSettings/ClusterInputManager.asset +++ /dev/null @@ -1,6 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!236 &1 -ClusterInputManager: - m_ObjectHideFlags: 0 - m_Inputs: [] diff --git a/sdks/csharp/ProjectSettings/DynamicsManager.asset b/sdks/csharp/ProjectSettings/DynamicsManager.asset deleted file mode 100644 index 5d5bacb2a5e..00000000000 --- a/sdks/csharp/ProjectSettings/DynamicsManager.asset +++ /dev/null @@ -1,36 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!55 &1 -PhysicsManager: - m_ObjectHideFlags: 0 - serializedVersion: 13 - m_Gravity: {x: 0, y: -9.81, z: 0} - m_DefaultMaterial: {fileID: 0} - m_BounceThreshold: 2 - m_SleepThreshold: 0.005 - m_DefaultContactOffset: 0.01 - m_DefaultSolverIterations: 6 - m_DefaultSolverVelocityIterations: 1 - m_QueriesHitBackfaces: 0 - m_QueriesHitTriggers: 1 - m_EnableAdaptiveForce: 0 - m_ClothInterCollisionDistance: 0.1 - m_ClothInterCollisionStiffness: 0.2 - m_ContactsGeneration: 1 - m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - m_AutoSimulation: 1 - m_AutoSyncTransforms: 0 - m_ReuseCollisionCallbacks: 1 - m_ClothInterCollisionSettingsToggle: 0 - m_ClothGravity: {x: 0, y: -9.81, z: 0} - m_ContactPairsMode: 0 - m_BroadphaseType: 0 - m_WorldBounds: - m_Center: {x: 0, y: 0, z: 0} - m_Extent: {x: 250, y: 250, z: 250} - m_WorldSubdivisions: 8 - m_FrictionType: 0 - m_EnableEnhancedDeterminism: 0 - m_EnableUnifiedHeightmaps: 1 - m_SolverType: 0 - m_DefaultMaxAngularSpeed: 7 diff --git a/sdks/csharp/ProjectSettings/EditorBuildSettings.asset b/sdks/csharp/ProjectSettings/EditorBuildSettings.asset deleted file mode 100644 index 2a4cbc567e2..00000000000 --- a/sdks/csharp/ProjectSettings/EditorBuildSettings.asset +++ /dev/null @@ -1,11 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1045 &1 -EditorBuildSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Scenes: - - enabled: 1 - path: Assets/Scenes/SampleScene.unity - guid: d1c3109bdb54ad54c8a2b2838528e640 - m_configObjects: {} diff --git a/sdks/csharp/ProjectSettings/EditorSettings.asset b/sdks/csharp/ProjectSettings/EditorSettings.asset deleted file mode 100644 index 05db6c812e9..00000000000 --- a/sdks/csharp/ProjectSettings/EditorSettings.asset +++ /dev/null @@ -1,31 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!159 &1 -EditorSettings: - m_AssetPipelineMode: 1 - m_ObjectHideFlags: 0 - serializedVersion: 10 - m_ExternalVersionControlSupport: Visible Meta Files - m_SerializationMode: 2 - m_LineEndingsForNewScripts: 0 - m_DefaultBehaviorMode: 0 - m_PrefabRegularEnvironment: {fileID: 0} - m_PrefabUIEnvironment: {fileID: 0} - m_SpritePackerMode: 0 - m_SpritePackerPaddingPower: 1 - m_EtcTextureCompressorBehavior: 1 - m_EtcTextureFastCompressor: 1 - m_EtcTextureNormalCompressor: 2 - m_EtcTextureBestCompressor: 4 - m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp - m_ProjectGenerationRootNamespace: - m_CollabEditorSettings: - inProgressEnabled: 1 - m_EnableTextureStreamingInEditMode: 1 - m_EnableTextureStreamingInPlayMode: 1 - m_AsyncShaderCompilation: 1 - m_EnterPlayModeOptionsEnabled: 0 - m_EnterPlayModeOptions: 3 - m_ShowLightmapResolutionOverlay: 1 - m_UseLegacyProbeSampleCount: 0 - m_SerializeInlineMappingsOnOneLine: 1 diff --git a/sdks/csharp/ProjectSettings/GraphicsSettings.asset b/sdks/csharp/ProjectSettings/GraphicsSettings.asset deleted file mode 100644 index db10dd6de06..00000000000 --- a/sdks/csharp/ProjectSettings/GraphicsSettings.asset +++ /dev/null @@ -1,68 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!30 &1 -GraphicsSettings: - m_ObjectHideFlags: 0 - serializedVersion: 13 - m_Deferred: - m_Mode: 1 - m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} - m_DeferredReflections: - m_Mode: 1 - m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} - m_ScreenSpaceShadows: - m_Mode: 1 - m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} - m_LegacyDeferred: - m_Mode: 1 - m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} - m_DepthNormals: - m_Mode: 1 - m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} - m_MotionVectors: - m_Mode: 1 - m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} - m_LightHalo: - m_Mode: 1 - m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} - m_LensFlare: - m_Mode: 1 - m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} - m_AlwaysIncludedShaders: - - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} - m_PreloadedShaders: [] - m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, - type: 0} - m_CustomRenderPipeline: {fileID: 11400000, guid: 19ba41d7c0026c3459d37c2fe90c55a0, - type: 2} - m_TransparencySortMode: 0 - m_TransparencySortAxis: {x: 0, y: 0, z: 1} - m_DefaultRenderingPath: 1 - m_DefaultMobileRenderingPath: 1 - m_TierSettings: [] - m_LightmapStripping: 0 - m_FogStripping: 0 - m_InstancingStripping: 0 - m_LightmapKeepPlain: 1 - m_LightmapKeepDirCombined: 1 - m_LightmapKeepDynamicPlain: 1 - m_LightmapKeepDynamicDirCombined: 1 - m_LightmapKeepShadowMask: 1 - m_LightmapKeepSubtractive: 1 - m_FogKeepLinear: 1 - m_FogKeepExp: 1 - m_FogKeepExp2: 1 - m_AlbedoSwatchInfos: [] - m_LightsUseLinearIntensity: 1 - m_LightsUseColorTemperature: 0 - m_LogWhenShaderIsCompiled: 0 - m_AllowEnlightenSupportForUpgradedProject: 1 diff --git a/sdks/csharp/ProjectSettings/InputManager.asset b/sdks/csharp/ProjectSettings/InputManager.asset deleted file mode 100644 index b16147e954f..00000000000 --- a/sdks/csharp/ProjectSettings/InputManager.asset +++ /dev/null @@ -1,487 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!13 &1 -InputManager: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Axes: - - serializedVersion: 3 - m_Name: Horizontal - descriptiveName: - descriptiveNegativeName: - negativeButton: left - positiveButton: right - altNegativeButton: a - altPositiveButton: d - gravity: 3 - dead: 0.001 - sensitivity: 3 - snap: 1 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Vertical - descriptiveName: - descriptiveNegativeName: - negativeButton: down - positiveButton: up - altNegativeButton: s - altPositiveButton: w - gravity: 3 - dead: 0.001 - sensitivity: 3 - snap: 1 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire1 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left ctrl - altNegativeButton: - altPositiveButton: mouse 0 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire2 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left alt - altNegativeButton: - altPositiveButton: mouse 1 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire3 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left shift - altNegativeButton: - altPositiveButton: mouse 2 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Jump - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: space - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse X - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse Y - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 1 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse ScrollWheel - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 2 - joyNum: 0 - - serializedVersion: 3 - m_Name: Horizontal - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0.19 - sensitivity: 1 - snap: 0 - invert: 0 - type: 2 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Vertical - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0.19 - sensitivity: 1 - snap: 0 - invert: 1 - type: 2 - axis: 1 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire1 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 0 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire2 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 1 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire3 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 2 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Jump - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 3 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Submit - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: return - altNegativeButton: - altPositiveButton: joystick button 0 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Submit - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: enter - altNegativeButton: - altPositiveButton: space - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Cancel - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: escape - altNegativeButton: - altPositiveButton: joystick button 1 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Enable Debug Button 1 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left ctrl - altNegativeButton: - altPositiveButton: joystick button 8 - gravity: 0 - dead: 0 - sensitivity: 0 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Enable Debug Button 2 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: backspace - altNegativeButton: - altPositiveButton: joystick button 9 - gravity: 0 - dead: 0 - sensitivity: 0 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Reset - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left alt - altNegativeButton: - altPositiveButton: joystick button 1 - gravity: 0 - dead: 0 - sensitivity: 0 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Next - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: page down - altNegativeButton: - altPositiveButton: joystick button 5 - gravity: 0 - dead: 0 - sensitivity: 0 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Previous - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: page up - altNegativeButton: - altPositiveButton: joystick button 4 - gravity: 0 - dead: 0 - sensitivity: 0 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Validate - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: return - altNegativeButton: - altPositiveButton: joystick button 0 - gravity: 0 - dead: 0 - sensitivity: 0 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Persistent - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: right shift - altNegativeButton: - altPositiveButton: joystick button 2 - gravity: 0 - dead: 0 - sensitivity: 0 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Multiplier - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left shift - altNegativeButton: - altPositiveButton: joystick button 3 - gravity: 0 - dead: 0 - sensitivity: 0 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Horizontal - descriptiveName: - descriptiveNegativeName: - negativeButton: left - positiveButton: right - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Vertical - descriptiveName: - descriptiveNegativeName: - negativeButton: down - positiveButton: up - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Vertical - descriptiveName: - descriptiveNegativeName: - negativeButton: down - positiveButton: up - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 2 - axis: 6 - joyNum: 0 - - serializedVersion: 3 - m_Name: Debug Horizontal - descriptiveName: - descriptiveNegativeName: - negativeButton: left - positiveButton: right - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 2 - axis: 5 - joyNum: 0 diff --git a/sdks/csharp/ProjectSettings/NavMeshAreas.asset b/sdks/csharp/ProjectSettings/NavMeshAreas.asset deleted file mode 100644 index 3b0b7c3d183..00000000000 --- a/sdks/csharp/ProjectSettings/NavMeshAreas.asset +++ /dev/null @@ -1,91 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!126 &1 -NavMeshProjectSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - areas: - - name: Walkable - cost: 1 - - name: Not Walkable - cost: 1 - - name: Jump - cost: 2 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - m_LastAgentTypeID: -887442657 - m_Settings: - - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.75 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_SettingNames: - - Humanoid diff --git a/sdks/csharp/ProjectSettings/PackageManagerSettings.asset b/sdks/csharp/ProjectSettings/PackageManagerSettings.asset deleted file mode 100644 index be4a7974ec1..00000000000 --- a/sdks/csharp/ProjectSettings/PackageManagerSettings.asset +++ /dev/null @@ -1,43 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &1 -MonoBehaviour: - m_ObjectHideFlags: 61 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_EnablePreviewPackages: 0 - m_EnablePackageDependencies: 0 - m_AdvancedSettingsExpanded: 1 - m_ScopedRegistriesSettingsExpanded: 1 - oneTimeWarningShown: 0 - m_Registries: - - m_Id: main - m_Name: - m_Url: https://packages.unity.com - m_Scopes: [] - m_IsDefault: 1 - m_Capabilities: 7 - m_UserSelectedRegistryName: - m_UserAddingNewScopedRegistry: 0 - m_RegistryInfoDraft: - m_ErrorMessage: - m_Original: - m_Id: - m_Name: - m_Url: - m_Scopes: [] - m_IsDefault: 0 - m_Capabilities: 0 - m_Modified: 0 - m_Name: - m_Url: - m_Scopes: - - - m_SelectedScopeIndex: 0 diff --git a/sdks/csharp/ProjectSettings/Physics2DSettings.asset b/sdks/csharp/ProjectSettings/Physics2DSettings.asset deleted file mode 100644 index 47880b1c8c8..00000000000 --- a/sdks/csharp/ProjectSettings/Physics2DSettings.asset +++ /dev/null @@ -1,56 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!19 &1 -Physics2DSettings: - m_ObjectHideFlags: 0 - serializedVersion: 4 - m_Gravity: {x: 0, y: -9.81} - m_DefaultMaterial: {fileID: 0} - m_VelocityIterations: 8 - m_PositionIterations: 3 - m_VelocityThreshold: 1 - m_MaxLinearCorrection: 0.2 - m_MaxAngularCorrection: 8 - m_MaxTranslationSpeed: 100 - m_MaxRotationSpeed: 360 - m_BaumgarteScale: 0.2 - m_BaumgarteTimeOfImpactScale: 0.75 - m_TimeToSleep: 0.5 - m_LinearSleepTolerance: 0.01 - m_AngularSleepTolerance: 2 - m_DefaultContactOffset: 0.01 - m_JobOptions: - serializedVersion: 2 - useMultithreading: 0 - useConsistencySorting: 0 - m_InterpolationPosesPerJob: 100 - m_NewContactsPerJob: 30 - m_CollideContactsPerJob: 100 - m_ClearFlagsPerJob: 200 - m_ClearBodyForcesPerJob: 200 - m_SyncDiscreteFixturesPerJob: 50 - m_SyncContinuousFixturesPerJob: 50 - m_FindNearestContactsPerJob: 100 - m_UpdateTriggerContactsPerJob: 100 - m_IslandSolverCostThreshold: 100 - m_IslandSolverBodyCostScale: 1 - m_IslandSolverContactCostScale: 10 - m_IslandSolverJointCostScale: 10 - m_IslandSolverBodiesPerJob: 50 - m_IslandSolverContactsPerJob: 50 - m_AutoSimulation: 1 - m_QueriesHitTriggers: 1 - m_QueriesStartInColliders: 1 - m_CallbacksOnDisable: 1 - m_ReuseCollisionCallbacks: 1 - m_AutoSyncTransforms: 0 - m_AlwaysShowColliders: 0 - m_ShowColliderSleep: 1 - m_ShowColliderContacts: 0 - m_ShowColliderAABB: 0 - m_ContactArrowScale: 0.2 - m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} - m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} - m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} - m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} - m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/sdks/csharp/ProjectSettings/PresetManager.asset b/sdks/csharp/ProjectSettings/PresetManager.asset deleted file mode 100644 index 10a1b07384a..00000000000 --- a/sdks/csharp/ProjectSettings/PresetManager.asset +++ /dev/null @@ -1,27 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1386491679 &1 -PresetManager: - m_ObjectHideFlags: 0 - m_DefaultList: - - type: - m_NativeTypeID: 108 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - defaultPresets: - - m_Preset: {fileID: 2655988077585873504, guid: 463065d4f17d1d94d848aa127b94dd43, - type: 2} - - type: - m_NativeTypeID: 1020 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - defaultPresets: - - m_Preset: {fileID: 2655988077585873504, guid: e7689051185d12f4298e1ebb2693a29f, - type: 2} - - type: - m_NativeTypeID: 1006 - m_ManagedTypePPtr: {fileID: 0} - m_ManagedTypeFallback: - defaultPresets: - - m_Preset: {fileID: 2655988077585873504, guid: e8537455c6c08bd4e8bf0be3707da685, - type: 2} diff --git a/sdks/csharp/ProjectSettings/ProjectSettings.asset b/sdks/csharp/ProjectSettings/ProjectSettings.asset deleted file mode 100644 index 4a28a37ec73..00000000000 --- a/sdks/csharp/ProjectSettings/ProjectSettings.asset +++ /dev/null @@ -1,698 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!129 &1 -PlayerSettings: - m_ObjectHideFlags: 0 - serializedVersion: 22 - productGUID: ab1ec9304db0f00cba3d0fdd5dffedf9 - AndroidProfiler: 0 - AndroidFilterTouchesWhenObscured: 0 - AndroidEnableSustainedPerformanceMode: 0 - defaultScreenOrientation: 4 - targetDevice: 2 - useOnDemandResources: 0 - accelerometerFrequency: 60 - companyName: DefaultCompany - productName: SpacetimeUnitySDK - defaultCursor: {fileID: 0} - cursorHotspot: {x: 0, y: 0} - m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} - m_ShowUnitySplashScreen: 1 - m_ShowUnitySplashLogo: 1 - m_SplashScreenOverlayOpacity: 1 - m_SplashScreenAnimation: 1 - m_SplashScreenLogoStyle: 1 - m_SplashScreenDrawMode: 0 - m_SplashScreenBackgroundAnimationZoom: 1 - m_SplashScreenLogoAnimationZoom: 1 - m_SplashScreenBackgroundLandscapeAspect: 1 - m_SplashScreenBackgroundPortraitAspect: 1 - m_SplashScreenBackgroundLandscapeUvs: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - m_SplashScreenBackgroundPortraitUvs: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - m_SplashScreenLogos: [] - m_VirtualRealitySplashScreen: {fileID: 0} - m_HolographicTrackingLossScreen: {fileID: 0} - defaultScreenWidth: 1920 - defaultScreenHeight: 1080 - defaultScreenWidthWeb: 960 - defaultScreenHeightWeb: 600 - m_StereoRenderingPath: 0 - m_ActiveColorSpace: 1 - m_MTRendering: 1 - mipStripping: 0 - numberOfMipsStripped: 0 - m_StackTraceTypes: 010000000100000001000000010000000100000001000000 - iosShowActivityIndicatorOnLoading: -1 - androidShowActivityIndicatorOnLoading: -1 - iosUseCustomAppBackgroundBehavior: 0 - iosAllowHTTPDownload: 1 - allowedAutorotateToPortrait: 1 - allowedAutorotateToPortraitUpsideDown: 1 - allowedAutorotateToLandscapeRight: 1 - allowedAutorotateToLandscapeLeft: 1 - useOSAutorotation: 1 - use32BitDisplayBuffer: 1 - preserveFramebufferAlpha: 0 - disableDepthAndStencilBuffers: 0 - androidStartInFullscreen: 1 - androidRenderOutsideSafeArea: 0 - androidUseSwappy: 1 - androidBlitType: 1 - androidResizableWindow: 0 - androidDefaultWindowWidth: 1920 - androidDefaultWindowHeight: 1080 - androidMinimumWindowWidth: 400 - androidMinimumWindowHeight: 300 - androidFullscreenMode: 1 - defaultIsNativeResolution: 1 - macRetinaSupport: 1 - runInBackground: 1 - captureSingleScreen: 0 - muteOtherAudioSources: 0 - Prepare IOS For Recording: 0 - Force IOS Speakers When Recording: 0 - deferSystemGesturesMode: 0 - hideHomeButton: 0 - submitAnalytics: 1 - usePlayerLog: 1 - bakeCollisionMeshes: 0 - forceSingleInstance: 0 - useFlipModelSwapchain: 1 - resizableWindow: 0 - useMacAppStoreValidation: 0 - macAppStoreCategory: public.app-category.games - gpuSkinning: 1 - xboxPIXTextureCapture: 0 - xboxEnableAvatar: 0 - xboxEnableKinect: 0 - xboxEnableKinectAutoTracking: 0 - xboxEnableFitness: 0 - visibleInBackground: 1 - allowFullscreenSwitch: 1 - fullscreenMode: 1 - xboxSpeechDB: 0 - xboxEnableHeadOrientation: 0 - xboxEnableGuest: 0 - xboxEnablePIXSampling: 0 - metalFramebufferOnly: 0 - xboxOneResolution: 0 - xboxOneSResolution: 0 - xboxOneXResolution: 3 - xboxOneMonoLoggingLevel: 0 - xboxOneLoggingLevel: 1 - xboxOneDisableEsram: 0 - xboxOneEnableTypeOptimization: 0 - xboxOnePresentImmediateThreshold: 0 - switchQueueCommandMemory: 0 - switchQueueControlMemory: 0 - switchQueueComputeMemory: 262144 - switchNVNShaderPoolsGranularity: 33554432 - switchNVNDefaultPoolsGranularity: 16777216 - switchNVNOtherPoolsGranularity: 16777216 - switchNVNMaxPublicTextureIDCount: 0 - switchNVNMaxPublicSamplerIDCount: 0 - stadiaPresentMode: 0 - stadiaTargetFramerate: 0 - vulkanNumSwapchainBuffers: 3 - vulkanEnableSetSRGBWrite: 0 - vulkanEnablePreTransform: 0 - vulkanEnableLateAcquireNextImage: 0 - vulkanEnableCommandBufferRecycling: 1 - m_SupportedAspectRatios: - 4:3: 1 - 5:4: 1 - 16:10: 1 - 16:9: 1 - Others: 1 - bundleVersion: 0.1 - preloadedAssets: [] - metroInputSource: 0 - wsaTransparentSwapchain: 0 - m_HolographicPauseOnTrackingLoss: 1 - xboxOneDisableKinectGpuReservation: 1 - xboxOneEnable7thCore: 1 - vrSettings: - enable360StereoCapture: 0 - isWsaHolographicRemotingEnabled: 0 - enableFrameTimingStats: 0 - useHDRDisplay: 0 - D3DHDRBitDepth: 0 - m_ColorGamuts: 0000000003000000 - targetPixelDensity: 30 - resolutionScalingMode: 0 - androidSupportedAspectRatio: 1 - androidMaxAspectRatio: 2.1 - applicationIdentifier: {} - buildNumber: - Standalone: 0 - iPhone: 0 - tvOS: 0 - overrideDefaultApplicationIdentifier: 0 - AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 19 - AndroidTargetSdkVersion: 0 - AndroidPreferredInstallLocation: 1 - aotOptions: - stripEngineCode: 1 - iPhoneStrippingLevel: 0 - iPhoneScriptCallOptimization: 0 - ForceInternetPermission: 0 - ForceSDCardPermission: 0 - CreateWallpaper: 0 - APKExpansionFiles: 0 - keepLoadedShadersAlive: 0 - StripUnusedMeshComponents: 0 - VertexChannelCompressionMask: 4054 - iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 11.0 - tvOSSdkVersion: 0 - tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: 11.0 - uIPrerenderedIcon: 0 - uIRequiresPersistentWiFi: 0 - uIRequiresFullScreen: 1 - uIStatusBarHidden: 1 - uIExitOnSuspend: 0 - uIStatusBarStyle: 0 - appleTVSplashScreen: {fileID: 0} - appleTVSplashScreen2x: {fileID: 0} - tvOSSmallIconLayers: [] - tvOSSmallIconLayers2x: [] - tvOSLargeIconLayers: [] - tvOSLargeIconLayers2x: [] - tvOSTopShelfImageLayers: [] - tvOSTopShelfImageLayers2x: [] - tvOSTopShelfImageWideLayers: [] - tvOSTopShelfImageWideLayers2x: [] - iOSLaunchScreenType: 0 - iOSLaunchScreenPortrait: {fileID: 0} - iOSLaunchScreenLandscape: {fileID: 0} - iOSLaunchScreenBackgroundColor: - serializedVersion: 2 - rgba: 0 - iOSLaunchScreenFillPct: 100 - iOSLaunchScreenSize: 100 - iOSLaunchScreenCustomXibPath: - iOSLaunchScreeniPadType: 0 - iOSLaunchScreeniPadImage: {fileID: 0} - iOSLaunchScreeniPadBackgroundColor: - serializedVersion: 2 - rgba: 0 - iOSLaunchScreeniPadFillPct: 100 - iOSLaunchScreeniPadSize: 100 - iOSLaunchScreeniPadCustomXibPath: - iOSLaunchScreenCustomStoryboardPath: - iOSLaunchScreeniPadCustomStoryboardPath: - iOSDeviceRequirements: [] - iOSURLSchemes: [] - iOSBackgroundModes: 0 - iOSMetalForceHardShadows: 0 - metalEditorSupport: 1 - metalAPIValidation: 1 - iOSRenderExtraFrameOnPause: 0 - iosCopyPluginsCodeInsteadOfSymlink: 0 - appleDeveloperTeamID: - iOSManualSigningProvisioningProfileID: - tvOSManualSigningProvisioningProfileID: - iOSManualSigningProvisioningProfileType: 0 - tvOSManualSigningProvisioningProfileType: 0 - appleEnableAutomaticSigning: 0 - iOSRequireARKit: 0 - iOSAutomaticallyDetectAndAddCapabilities: 1 - appleEnableProMotion: 0 - shaderPrecisionModel: 0 - clonedFromGUID: 9870af204204ab84596f8a656f2f2ce6 - templatePackageId: com.unity.template.universal@10.7.0 - templateDefaultScene: Assets/Scenes/SampleScene.unity - useCustomMainManifest: 0 - useCustomLauncherManifest: 0 - useCustomMainGradleTemplate: 0 - useCustomLauncherGradleManifest: 0 - useCustomBaseGradleTemplate: 0 - useCustomGradlePropertiesTemplate: 0 - useCustomProguardFile: 0 - AndroidTargetArchitectures: 1 - AndroidTargetDevices: 0 - AndroidSplashScreenScale: 0 - androidSplashScreen: {fileID: 0} - AndroidKeystoreName: - AndroidKeyaliasName: - AndroidBuildApkPerCpuArchitecture: 0 - AndroidTVCompatibility: 0 - AndroidIsGame: 1 - AndroidEnableTango: 0 - androidEnableBanner: 1 - androidUseLowAccuracyLocation: 0 - androidUseCustomKeystore: 0 - m_AndroidBanners: - - width: 320 - height: 180 - banner: {fileID: 0} - androidGamepadSupportLevel: 0 - chromeosInputEmulation: 1 - AndroidMinifyWithR8: 0 - AndroidMinifyRelease: 0 - AndroidMinifyDebug: 0 - AndroidValidateAppBundleSize: 1 - AndroidAppBundleSizeToValidate: 100 - m_BuildTargetIcons: [] - m_BuildTargetPlatformIcons: [] - m_BuildTargetBatching: - - m_BuildTarget: Standalone - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: tvOS - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: iPhone - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: Android - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: WebGL - m_StaticBatching: 0 - m_DynamicBatching: 0 - m_BuildTargetGraphicsJobs: - - m_BuildTarget: MacStandaloneSupport - m_GraphicsJobs: 0 - - m_BuildTarget: Switch - m_GraphicsJobs: 1 - - m_BuildTarget: MetroSupport - m_GraphicsJobs: 1 - - m_BuildTarget: AppleTVSupport - m_GraphicsJobs: 0 - - m_BuildTarget: BJMSupport - m_GraphicsJobs: 1 - - m_BuildTarget: LinuxStandaloneSupport - m_GraphicsJobs: 1 - - m_BuildTarget: PS4Player - m_GraphicsJobs: 1 - - m_BuildTarget: iOSSupport - m_GraphicsJobs: 0 - - m_BuildTarget: WindowsStandaloneSupport - m_GraphicsJobs: 1 - - m_BuildTarget: XboxOnePlayer - m_GraphicsJobs: 1 - - m_BuildTarget: LuminSupport - m_GraphicsJobs: 0 - - m_BuildTarget: AndroidPlayer - m_GraphicsJobs: 0 - - m_BuildTarget: WebGLSupport - m_GraphicsJobs: 0 - m_BuildTargetGraphicsJobMode: - - m_BuildTarget: PS4Player - m_GraphicsJobMode: 0 - - m_BuildTarget: XboxOnePlayer - m_GraphicsJobMode: 0 - m_BuildTargetGraphicsAPIs: - - m_BuildTarget: iOSSupport - m_APIs: 10000000 - m_Automatic: 1 - - m_BuildTarget: AppleTVSupport - m_APIs: 10000000 - m_Automatic: 1 - - m_BuildTarget: AndroidPlayer - m_APIs: 150000000b000000 - m_Automatic: 0 - - m_BuildTarget: WebGLSupport - m_APIs: 0b000000 - m_Automatic: 0 - m_BuildTargetVRSettings: [] - openGLRequireES31: 0 - openGLRequireES31AEP: 0 - openGLRequireES32: 0 - m_TemplateCustomTags: {} - mobileMTRendering: - Android: 1 - iPhone: 1 - tvOS: 1 - m_BuildTargetGroupLightmapEncodingQuality: - - m_BuildTarget: Standalone - m_EncodingQuality: 1 - m_BuildTargetGroupLightmapSettings: [] - m_BuildTargetNormalMapEncoding: [] - playModeTestRunnerEnabled: 0 - runPlayModeTestAsEditModeTest: 0 - actionOnDotNetUnhandledException: 1 - enableInternalProfiler: 0 - logObjCUncaughtExceptions: 1 - enableCrashReportAPI: 0 - cameraUsageDescription: - locationUsageDescription: - microphoneUsageDescription: - bluetoothUsageDescription: - switchNMETAOverride: - switchNetLibKey: - switchSocketMemoryPoolSize: 6144 - switchSocketAllocatorPoolSize: 128 - switchSocketConcurrencyLimit: 14 - switchScreenResolutionBehavior: 2 - switchUseCPUProfiler: 0 - switchUseGOLDLinker: 0 - switchApplicationID: 0x01004b9000490000 - switchNSODependencies: - switchTitleNames_0: - switchTitleNames_1: - switchTitleNames_2: - switchTitleNames_3: - switchTitleNames_4: - switchTitleNames_5: - switchTitleNames_6: - switchTitleNames_7: - switchTitleNames_8: - switchTitleNames_9: - switchTitleNames_10: - switchTitleNames_11: - switchTitleNames_12: - switchTitleNames_13: - switchTitleNames_14: - switchTitleNames_15: - switchPublisherNames_0: - switchPublisherNames_1: - switchPublisherNames_2: - switchPublisherNames_3: - switchPublisherNames_4: - switchPublisherNames_5: - switchPublisherNames_6: - switchPublisherNames_7: - switchPublisherNames_8: - switchPublisherNames_9: - switchPublisherNames_10: - switchPublisherNames_11: - switchPublisherNames_12: - switchPublisherNames_13: - switchPublisherNames_14: - switchPublisherNames_15: - switchIcons_0: {fileID: 0} - switchIcons_1: {fileID: 0} - switchIcons_2: {fileID: 0} - switchIcons_3: {fileID: 0} - switchIcons_4: {fileID: 0} - switchIcons_5: {fileID: 0} - switchIcons_6: {fileID: 0} - switchIcons_7: {fileID: 0} - switchIcons_8: {fileID: 0} - switchIcons_9: {fileID: 0} - switchIcons_10: {fileID: 0} - switchIcons_11: {fileID: 0} - switchIcons_12: {fileID: 0} - switchIcons_13: {fileID: 0} - switchIcons_14: {fileID: 0} - switchIcons_15: {fileID: 0} - switchSmallIcons_0: {fileID: 0} - switchSmallIcons_1: {fileID: 0} - switchSmallIcons_2: {fileID: 0} - switchSmallIcons_3: {fileID: 0} - switchSmallIcons_4: {fileID: 0} - switchSmallIcons_5: {fileID: 0} - switchSmallIcons_6: {fileID: 0} - switchSmallIcons_7: {fileID: 0} - switchSmallIcons_8: {fileID: 0} - switchSmallIcons_9: {fileID: 0} - switchSmallIcons_10: {fileID: 0} - switchSmallIcons_11: {fileID: 0} - switchSmallIcons_12: {fileID: 0} - switchSmallIcons_13: {fileID: 0} - switchSmallIcons_14: {fileID: 0} - switchSmallIcons_15: {fileID: 0} - switchManualHTML: - switchAccessibleURLs: - switchLegalInformation: - switchMainThreadStackSize: 1048576 - switchPresenceGroupId: - switchLogoHandling: 0 - switchReleaseVersion: 0 - switchDisplayVersion: 1.0.0 - switchStartupUserAccount: 0 - switchTouchScreenUsage: 0 - switchSupportedLanguagesMask: 0 - switchLogoType: 0 - switchApplicationErrorCodeCategory: - switchUserAccountSaveDataSize: 0 - switchUserAccountSaveDataJournalSize: 0 - switchApplicationAttribute: 0 - switchCardSpecSize: -1 - switchCardSpecClock: -1 - switchRatingsMask: 0 - switchRatingsInt_0: 0 - switchRatingsInt_1: 0 - switchRatingsInt_2: 0 - switchRatingsInt_3: 0 - switchRatingsInt_4: 0 - switchRatingsInt_5: 0 - switchRatingsInt_6: 0 - switchRatingsInt_7: 0 - switchRatingsInt_8: 0 - switchRatingsInt_9: 0 - switchRatingsInt_10: 0 - switchRatingsInt_11: 0 - switchRatingsInt_12: 0 - switchLocalCommunicationIds_0: - switchLocalCommunicationIds_1: - switchLocalCommunicationIds_2: - switchLocalCommunicationIds_3: - switchLocalCommunicationIds_4: - switchLocalCommunicationIds_5: - switchLocalCommunicationIds_6: - switchLocalCommunicationIds_7: - switchParentalControl: 0 - switchAllowsScreenshot: 1 - switchAllowsVideoCapturing: 1 - switchAllowsRuntimeAddOnContentInstall: 0 - switchDataLossConfirmation: 0 - switchUserAccountLockEnabled: 0 - switchSystemResourceMemory: 16777216 - switchSupportedNpadStyles: 22 - switchNativeFsCacheSize: 32 - switchIsHoldTypeHorizontal: 0 - switchSupportedNpadCount: 8 - switchSocketConfigEnabled: 0 - switchTcpInitialSendBufferSize: 32 - switchTcpInitialReceiveBufferSize: 64 - switchTcpAutoSendBufferSizeMax: 256 - switchTcpAutoReceiveBufferSizeMax: 256 - switchUdpSendBufferSize: 9 - switchUdpReceiveBufferSize: 42 - switchSocketBufferEfficiency: 4 - switchSocketInitializeEnabled: 1 - switchNetworkInterfaceManagerInitializeEnabled: 1 - switchPlayerConnectionEnabled: 1 - switchUseNewStyleFilepaths: 0 - switchUseMicroSleepForYield: 1 - switchMicroSleepForYieldTime: 25 - ps4NPAgeRating: 12 - ps4NPTitleSecret: - ps4NPTrophyPackPath: - ps4ParentalLevel: 11 - ps4ContentID: ED1633-NPXX51362_00-0000000000000000 - ps4Category: 0 - ps4MasterVersion: 01.00 - ps4AppVersion: 01.00 - ps4AppType: 0 - ps4ParamSfxPath: - ps4VideoOutPixelFormat: 0 - ps4VideoOutInitialWidth: 1920 - ps4VideoOutBaseModeInitialWidth: 1920 - ps4VideoOutReprojectionRate: 60 - ps4PronunciationXMLPath: - ps4PronunciationSIGPath: - ps4BackgroundImagePath: - ps4StartupImagePath: - ps4StartupImagesFolder: - ps4IconImagesFolder: - ps4SaveDataImagePath: - ps4SdkOverride: - ps4BGMPath: - ps4ShareFilePath: - ps4ShareOverlayImagePath: - ps4PrivacyGuardImagePath: - ps4ExtraSceSysFile: - ps4NPtitleDatPath: - ps4RemotePlayKeyAssignment: -1 - ps4RemotePlayKeyMappingDir: - ps4PlayTogetherPlayerCount: 0 - ps4EnterButtonAssignment: 1 - ps4ApplicationParam1: 0 - ps4ApplicationParam2: 0 - ps4ApplicationParam3: 0 - ps4ApplicationParam4: 0 - ps4DownloadDataSize: 0 - ps4GarlicHeapSize: 2048 - ps4ProGarlicHeapSize: 2560 - playerPrefsMaxSize: 32768 - ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ - ps4pnSessions: 1 - ps4pnPresence: 1 - ps4pnFriends: 1 - ps4pnGameCustomData: 1 - playerPrefsSupport: 0 - enableApplicationExit: 0 - resetTempFolder: 1 - restrictedAudioUsageRights: 0 - ps4UseResolutionFallback: 0 - ps4ReprojectionSupport: 0 - ps4UseAudio3dBackend: 0 - ps4UseLowGarlicFragmentationMode: 1 - ps4SocialScreenEnabled: 0 - ps4ScriptOptimizationLevel: 0 - ps4Audio3dVirtualSpeakerCount: 14 - ps4attribCpuUsage: 0 - ps4PatchPkgPath: - ps4PatchLatestPkgPath: - ps4PatchChangeinfoPath: - ps4PatchDayOne: 0 - ps4attribUserManagement: 0 - ps4attribMoveSupport: 0 - ps4attrib3DSupport: 0 - ps4attribShareSupport: 0 - ps4attribExclusiveVR: 0 - ps4disableAutoHideSplash: 0 - ps4videoRecordingFeaturesUsed: 0 - ps4contentSearchFeaturesUsed: 0 - ps4CompatibilityPS5: 0 - ps4AllowPS5Detection: 0 - ps4GPU800MHz: 1 - ps4attribEyeToEyeDistanceSettingVR: 0 - ps4IncludedModules: - - libc.prx - - libSceAudioLatencyEstimation.prx - - libSceFace.prx - - libSceFaceTracker.prx - - libSceFios2.prx - - libSceHand.prx - - libSceHandTracker.prx - - libSceHeadTracker.prx - - libSceJobManager.prx - - libSceNpToolkit2.prx - - libSceS3DConversion.prx - ps4attribVROutputEnabled: 0 - monoEnv: - splashScreenBackgroundSourceLandscape: {fileID: 0} - splashScreenBackgroundSourcePortrait: {fileID: 0} - blurSplashScreenBackground: 1 - spritePackerPolicy: - webGLMemorySize: 16 - webGLExceptionSupport: 1 - webGLNameFilesAsHashes: 0 - webGLDataCaching: 1 - webGLDebugSymbols: 0 - webGLEmscriptenArgs: - webGLModulesDirectory: - webGLTemplate: APPLICATION:Default - webGLAnalyzeBuildSize: 0 - webGLUseEmbeddedResources: 0 - webGLCompressionFormat: 1 - webGLWasmArithmeticExceptions: 0 - webGLLinkerTarget: 1 - webGLThreadsSupport: 0 - webGLDecompressionFallback: 0 - scriptingDefineSymbols: {} - additionalCompilerArguments: {} - platformArchitecture: {} - scriptingBackend: - Standalone: 0 - il2cppCompilerConfiguration: {} - managedStrippingLevel: {} - incrementalIl2cppBuild: {} - suppressCommonWarnings: 1 - allowUnsafeCode: 0 - useDeterministicCompilation: 1 - useReferenceAssemblies: 1 - enableRoslynAnalyzers: 1 - additionalIl2CppArgs: - scriptingRuntimeVersion: 1 - gcIncremental: 1 - assemblyVersionValidation: 1 - gcWBarrierValidation: 0 - apiCompatibilityLevelPerPlatform: - Standalone: 3 - m_RenderingPath: 1 - m_MobileRenderingPath: 1 - metroPackageName: Template_Lightweight - metroPackageVersion: - metroCertificatePath: - metroCertificatePassword: - metroCertificateSubject: - metroCertificateIssuer: - metroCertificateNotAfter: 0000000000000000 - metroApplicationDescription: Template_Lightweight - wsaImages: {} - metroTileShortName: - metroTileShowName: 0 - metroMediumTileShowName: 0 - metroLargeTileShowName: 0 - metroWideTileShowName: 0 - metroSupportStreamingInstall: 0 - metroLastRequiredScene: 0 - metroDefaultTileSize: 1 - metroTileForegroundText: 2 - metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} - metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1} - metroSplashScreenUseBackgroundColor: 0 - platformCapabilities: {} - metroTargetDeviceFamilies: {} - metroFTAName: - metroFTAFileTypes: [] - metroProtocolName: - XboxOneProductId: - XboxOneUpdateKey: - XboxOneSandboxId: - XboxOneContentId: - XboxOneTitleId: - XboxOneSCId: - XboxOneGameOsOverridePath: - XboxOnePackagingOverridePath: - XboxOneAppManifestOverridePath: - XboxOneVersion: 1.0.0.0 - XboxOnePackageEncryption: 0 - XboxOnePackageUpdateGranularity: 2 - XboxOneDescription: - XboxOneLanguage: - - enus - XboxOneCapability: [] - XboxOneGameRating: {} - XboxOneIsContentPackage: 0 - XboxOneEnhancedXboxCompatibilityMode: 0 - XboxOneEnableGPUVariability: 1 - XboxOneSockets: {} - XboxOneSplashScreen: {fileID: 0} - XboxOneAllowedProductIds: [] - XboxOnePersistentLocalStorageSize: 0 - XboxOneXTitleMemory: 8 - XboxOneOverrideIdentityName: - XboxOneOverrideIdentityPublisher: - vrEditorSettings: {} - cloudServicesEnabled: - UNet: 1 - luminIcon: - m_Name: - m_ModelFolderPath: - m_PortalFolderPath: - luminCert: - m_CertPath: - m_SignPackage: 1 - luminIsChannelApp: 0 - luminVersion: - m_VersionCode: 1 - m_VersionName: - apiCompatibilityLevel: 6 - activeInputHandler: 0 - cloudProjectId: - framebufferDepthMemorylessMode: 0 - qualitySettingsNames: [] - projectName: - organizationId: - cloudEnabled: 0 - legacyClampBlendShapeWeights: 0 - virtualTexturingSupportEnabled: 0 diff --git a/sdks/csharp/ProjectSettings/ProjectVersion.txt b/sdks/csharp/ProjectSettings/ProjectVersion.txt deleted file mode 100644 index 4c9401b919c..00000000000 --- a/sdks/csharp/ProjectSettings/ProjectVersion.txt +++ /dev/null @@ -1,2 +0,0 @@ -m_EditorVersion: 2020.3.25f1 -m_EditorVersionWithRevision: 2020.3.25f1 (9b9180224418) diff --git a/sdks/csharp/ProjectSettings/QualitySettings.asset b/sdks/csharp/ProjectSettings/QualitySettings.asset deleted file mode 100644 index dad5d50cfff..00000000000 --- a/sdks/csharp/ProjectSettings/QualitySettings.asset +++ /dev/null @@ -1,128 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!47 &1 -QualitySettings: - m_ObjectHideFlags: 0 - serializedVersion: 5 - m_CurrentQuality: 2 - m_QualitySettings: - - serializedVersion: 2 - name: Low - pixelLightCount: 0 - shadows: 0 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 20 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - skinWeights: 2 - textureQuality: 0 - anisotropicTextures: 0 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 0 - lodBias: 0.4 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 16 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 11400000, guid: a31e9f9f9c9d4b9429ed0d1234e22103, type: 2} - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Medium - pixelLightCount: 1 - shadows: 1 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 20 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - skinWeights: 2 - textureQuality: 0 - anisotropicTextures: 1 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 1 - lodBias: 0.7 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 64 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 11400000, guid: d847b876476d3d6468f5dfcd34266f96, type: 2} - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: High - pixelLightCount: 2 - shadows: 2 - shadowResolution: 1 - shadowProjection: 1 - shadowCascades: 2 - shadowDistance: 40 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - skinWeights: 2 - textureQuality: 0 - anisotropicTextures: 1 - antiAliasing: 2 - softParticles: 0 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 1 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 256 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 11400000, guid: 19ba41d7c0026c3459d37c2fe90c55a0, type: 2} - excludedTargetPlatforms: [] - m_PerPlatformDefaultQuality: - Android: 1 - Lumin: 2 - Nintendo Switch: 2 - PS4: 2 - Stadia: 2 - Standalone: 2 - WebGL: 1 - Windows Store Apps: 2 - XboxOne: 2 - iPhone: 1 - tvOS: 1 diff --git a/sdks/csharp/ProjectSettings/SceneTemplateSettings.json b/sdks/csharp/ProjectSettings/SceneTemplateSettings.json deleted file mode 100644 index 6f3e60fd8b7..00000000000 --- a/sdks/csharp/ProjectSettings/SceneTemplateSettings.json +++ /dev/null @@ -1,167 +0,0 @@ -{ - "templatePinStates": [], - "dependencyTypeInfos": [ - { - "userAdded": false, - "type": "UnityEngine.AnimationClip", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEditor.Animations.AnimatorController", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.AnimatorOverrideController", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEditor.Audio.AudioMixerController", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.ComputeShader", - "ignore": true, - "defaultInstantiationMode": 1, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.Cubemap", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.GameObject", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEditor.LightingDataAsset", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": false - }, - { - "userAdded": false, - "type": "UnityEngine.LightingSettings", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.Material", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEditor.MonoScript", - "ignore": true, - "defaultInstantiationMode": 1, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.PhysicMaterial", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.PhysicsMaterial2D", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.VolumeProfile", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEditor.SceneAsset", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": false - }, - { - "userAdded": false, - "type": "UnityEngine.Shader", - "ignore": true, - "defaultInstantiationMode": 1, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.ShaderVariantCollection", - "ignore": true, - "defaultInstantiationMode": 1, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.Texture", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.Texture2D", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - }, - { - "userAdded": false, - "type": "UnityEngine.Timeline.TimelineAsset", - "ignore": false, - "defaultInstantiationMode": 0, - "supportsModification": true - } - ], - "defaultDependencyTypeInfo": { - "userAdded": false, - "type": "", - "ignore": false, - "defaultInstantiationMode": 1, - "supportsModification": true - }, - "newSceneOverride": 0 -} \ No newline at end of file diff --git a/sdks/csharp/ProjectSettings/TagManager.asset b/sdks/csharp/ProjectSettings/TagManager.asset deleted file mode 100644 index 1c92a7840ec..00000000000 --- a/sdks/csharp/ProjectSettings/TagManager.asset +++ /dev/null @@ -1,43 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!78 &1 -TagManager: - serializedVersion: 2 - tags: [] - layers: - - Default - - TransparentFX - - Ignore Raycast - - - - Water - - UI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - m_SortingLayers: - - name: Default - uniqueID: 0 - locked: 0 diff --git a/sdks/csharp/ProjectSettings/TimeManager.asset b/sdks/csharp/ProjectSettings/TimeManager.asset deleted file mode 100644 index 06bcc6d2953..00000000000 --- a/sdks/csharp/ProjectSettings/TimeManager.asset +++ /dev/null @@ -1,9 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!5 &1 -TimeManager: - m_ObjectHideFlags: 0 - Fixed Timestep: 0.02 - Maximum Allowed Timestep: 0.1 - m_TimeScale: 1 - Maximum Particle Timestep: 0.03 diff --git a/sdks/csharp/ProjectSettings/URPProjectSettings.asset b/sdks/csharp/ProjectSettings/URPProjectSettings.asset deleted file mode 100644 index 3077404f36b..00000000000 --- a/sdks/csharp/ProjectSettings/URPProjectSettings.asset +++ /dev/null @@ -1,15 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &1 -MonoBehaviour: - m_ObjectHideFlags: 61 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3} - m_Name: - m_EditorClassIdentifier: - m_LastMaterialVersion: 4 diff --git a/sdks/csharp/ProjectSettings/UnityConnectSettings.asset b/sdks/csharp/ProjectSettings/UnityConnectSettings.asset deleted file mode 100644 index 6125b308af4..00000000000 --- a/sdks/csharp/ProjectSettings/UnityConnectSettings.asset +++ /dev/null @@ -1,35 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!310 &1 -UnityConnectSettings: - m_ObjectHideFlags: 0 - serializedVersion: 1 - m_Enabled: 0 - m_TestMode: 0 - m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events - m_EventUrl: https://cdp.cloud.unity3d.com/v1/events - m_ConfigUrl: https://config.uca.cloud.unity3d.com - m_DashboardUrl: https://dashboard.unity3d.com - m_TestInitMode: 0 - CrashReportingSettings: - m_EventUrl: https://perf-events.cloud.unity3d.com - m_Enabled: 0 - m_LogBufferSize: 10 - m_CaptureEditorExceptions: 1 - UnityPurchasingSettings: - m_Enabled: 0 - m_TestMode: 0 - UnityAnalyticsSettings: - m_Enabled: 0 - m_TestMode: 0 - m_InitializeOnStartup: 1 - UnityAdsSettings: - m_Enabled: 0 - m_InitializeOnStartup: 1 - m_TestMode: 0 - m_IosGameId: - m_AndroidGameId: - m_GameIds: {} - m_GameId: - PerformanceReportingSettings: - m_Enabled: 0 diff --git a/sdks/csharp/ProjectSettings/VFXManager.asset b/sdks/csharp/ProjectSettings/VFXManager.asset deleted file mode 100644 index 6e0eaca40d5..00000000000 --- a/sdks/csharp/ProjectSettings/VFXManager.asset +++ /dev/null @@ -1,11 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!937362698 &1 -VFXManager: - m_ObjectHideFlags: 0 - m_IndirectShader: {fileID: 0} - m_CopyBufferShader: {fileID: 0} - m_SortShader: {fileID: 0} - m_RenderPipeSettingsPath: - m_FixedTimeStep: 0.016666668 - m_MaxDeltaTime: 0.05 diff --git a/sdks/csharp/ProjectSettings/VersionControlSettings.asset b/sdks/csharp/ProjectSettings/VersionControlSettings.asset deleted file mode 100644 index dca288142fc..00000000000 --- a/sdks/csharp/ProjectSettings/VersionControlSettings.asset +++ /dev/null @@ -1,8 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!890905787 &1 -VersionControlSettings: - m_ObjectHideFlags: 0 - m_Mode: Visible Meta Files - m_CollabEditorSettings: - inProgressEnabled: 1 diff --git a/sdks/csharp/ProjectSettings/XRSettings.asset b/sdks/csharp/ProjectSettings/XRSettings.asset deleted file mode 100644 index 482590c196f..00000000000 --- a/sdks/csharp/ProjectSettings/XRSettings.asset +++ /dev/null @@ -1,10 +0,0 @@ -{ - "m_SettingKeys": [ - "VR Device Disabled", - "VR Device User Alert" - ], - "m_SettingValues": [ - "False", - "False" - ] -} \ No newline at end of file diff --git a/sdks/csharp/SpacetimeDBCSharpSDK.csproj b/sdks/csharp/SpacetimeDBCSharpSDK.csproj new file mode 100644 index 00000000000..04e55ba1342 --- /dev/null +++ b/sdks/csharp/SpacetimeDBCSharpSDK.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + + + + + + + + diff --git a/sdks/csharp/export.sh b/sdks/csharp/export.sh deleted file mode 100755 index 32e56df1925..00000000000 --- a/sdks/csharp/export.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -if [ -z "$UNITY_PATH" ]; then - unameOut="$(uname -s)" - case "${unameOut}" in - Linux*) export UNITY_PATH="$HOME/Unity/Hub/Editor/2020.3.25f1/Editor/Unity";; - Darwin*) export UNITY_PATH="/Applications/Unity/Hub/Editor/2020.3.25f1/Unity.app/Contents/MacOS/Unity";; - CYGWIN*) echo "Windows not supported, use WSL instead." && exit 1;; - MINGW*) echo "Windows not supported, use WSL instead." && exit 1;; - *) machine="UNKNOWN:${unameOut}" - esac - echo ${machine} - -fi - -if [ ! -f $UNITY_PATH ]; then - echo "Unable to find a version of Unity. Please specify it using UNITY_PATH :)" - exit 1 -fi - -$UNITY_PATH -projectPath . -quit -batchmode -nographics -ignorecompilererrors -executeMethod "ExportPackage.Export" diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs b/sdks/csharp/src/ByteArrayConverter.cs similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/ByteArrayConverter.cs rename to sdks/csharp/src/ByteArrayConverter.cs diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs b/sdks/csharp/src/ClientApi.cs similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApi.cs rename to sdks/csharp/src/ClientApi.cs diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs b/sdks/csharp/src/ClientApiExtensions.cs similarity index 51% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs rename to sdks/csharp/src/ClientApiExtensions.cs index 770bc9727df..f4445af11bc 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientApiExtensions.cs +++ b/sdks/csharp/src/ClientApiExtensions.cs @@ -2,6 +2,6 @@ { public partial class FunctionCall { - public SpacetimeDB.ReducerEvent CallInfo { get; internal set; } + public SpacetimeDB.ReducerEventBase CallInfo { get; set; } } } \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs b/sdks/csharp/src/ClientCache.cs similarity index 87% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs rename to sdks/csharp/src/ClientCache.cs index bd7ad2b2db8..fa9c76f8b20 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -6,7 +6,6 @@ using System.Net.Http.Headers; using System.Reflection; using Google.Protobuf; -using UnityEngine; using ClientApi; using SpacetimeDB.SATS; @@ -16,6 +15,26 @@ public class ClientCache { public class TableCache { + public class ByteArrayComparer : IEqualityComparer + { + public bool Equals(byte[] left, byte[] right) + { + if (left == null || right == null) + { + return left == right; + } + + return left.SequenceEqual(right); + } + + public int GetHashCode(byte[] key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + return key.Sum(b => b); + } + } + private readonly string name; private readonly Type clientTableType; private readonly AlgebraicType rowSchema; @@ -41,7 +60,7 @@ public Type ClientTableType public Action DeleteCallback; public Action UpdateCallback; // TODO: Consider renaming this one, this kind of implies that its a callback for the Update operation - public Action RowUpdatedCallback; + public Action RowUpdatedCallback; public Func ComparePrimaryKeyFunc; public string Name @@ -67,8 +86,8 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func)clientTableType.GetMethod("OnBeforeDeleteEvent")?.CreateDelegate(typeof(Action)); DeleteCallback = (Action)clientTableType.GetMethod("OnDeleteEvent")?.CreateDelegate(typeof(Action)); UpdateCallback = (Action)clientTableType.GetMethod("OnUpdateEvent")?.CreateDelegate(typeof(Action)); - RowUpdatedCallback = (Action)clientTableType.GetMethod("OnRowUpdateEvent") - ?.CreateDelegate(typeof(Action)); + RowUpdatedCallback = (Action)clientTableType.GetMethod("OnRowUpdateEvent") + ?.CreateDelegate(typeof(Action)); ComparePrimaryKeyFunc = (Func)clientTableType.GetMethod("ComparePrimaryKey", BindingFlags.Static | BindingFlags.Public) ?.CreateDelegate(typeof(Func)); entries = new Dictionary(new ByteArrayComparer()); @@ -128,7 +147,7 @@ public object InsertEntry(byte[] rowPk) } // Read failure - Debug.LogError( + SpacetimeDBClient.instance.Logger.LogError( $"Read error when converting row value for table: {clientTableType.Name} rowPk={Convert.ToBase64String(rowPk)} (version issue?)"); return null; } @@ -163,11 +182,11 @@ public object DeleteEntry(byte[] rowPk) // fabricate the deletion by trying to look it up in our local decode table. if (decodedValues.TryGetValue(rowPk, out var decodedValue)) { - Debug.LogWarning("Deleting value that we don't have (using cached value)"); + SpacetimeDBClient.instance.Logger.LogWarning("Deleting value that we don't have (using cached value)"); return decodedValue.Item2; } - Debug.LogWarning("Deleting value that we don't have (no cached value available)"); + SpacetimeDBClient.instance.Logger.LogWarning("Deleting value that we don't have (no cached value available)"); return null; } @@ -192,7 +211,7 @@ public bool ComparePrimaryKey(AlgebraicValue v1, AlgebraicValue v2) { return (bool)ComparePrimaryKeyFunc.Invoke(rowSchema, v1, v2); } - + public bool ComparePrimaryKey(byte[] rowPk1, byte[] rowPk2) { if (!decodedValues.TryGetValue(rowPk1, out var v1)) @@ -203,7 +222,7 @@ public bool ComparePrimaryKey(byte[] rowPk1, byte[] rowPk2) { return false; } - + return (bool)ComparePrimaryKeyFunc.Invoke(rowSchema, v1.Item1, v2.Item1); } } @@ -217,7 +236,7 @@ public void AddTable(Type clientTableType, AlgebraicType tableRowDef, Func PlayerPrefs.GetString(GetTokenKey()); + + public static void SaveToken(string token) + { + PlayerPrefs.SetString(GetTokenKey(), token); + } + + public static string GetTokenKey() + { + var key = "spacetimedb.identity_token"; +#if UNITY_EDITOR + // Different editors need different keys + key += $" - {Application.dataPath}"; +#endif + return key; + } + } + + public class NetworkManager : MonoBehaviour + { + protected void Awake() + { + // If you get a compile error on `Reducer`, that means you need to run the SpacetimeDB CLI generate command + SpacetimeDBClient.CreateInstance(new UnityDebugLogger(), typeof(Reducer)); + } + + private void OnDestroy() + { + SpacetimeDBClient.instance.Close(); + } + + private void Update() + { + SpacetimeDBClient.instance.Update(); + } + } +} +#endif \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs b/sdks/csharp/src/ReducerExtensions.cs similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerExtensions.cs rename to sdks/csharp/src/ReducerExtensions.cs diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs b/sdks/csharp/src/ReducerMismatchException.cs similarity index 88% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs rename to sdks/csharp/src/ReducerMismatchException.cs index bf36126479e..799d46ff501 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/ReducerMismatchException.cs +++ b/sdks/csharp/src/ReducerMismatchException.cs @@ -6,7 +6,7 @@ namespace SpacetimeDB { - class ReducerMismatchException : Exception + public class ReducerMismatchException : Exception { public ReducerMismatchException(string originalReducerName, string attemptedConversionReducerName) : base($"Cannot cast agruments from {originalReducerName} reducer call into {attemptedConversionReducerName} reducer arguments") diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs b/sdks/csharp/src/SATS/AlgebraicType.cs similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicType.cs rename to sdks/csharp/src/SATS/AlgebraicType.cs diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs b/sdks/csharp/src/SATS/AlgebraicValue.cs similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/AlgebraicValue.cs rename to sdks/csharp/src/SATS/AlgebraicValue.cs diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs b/sdks/csharp/src/SATS/Typespace.cs similarity index 93% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs rename to sdks/csharp/src/SATS/Typespace.cs index 307e16a5e1b..0604ee9d1bf 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/SATS/Typespace.cs +++ b/sdks/csharp/src/SATS/Typespace.cs @@ -1,7 +1,5 @@ using System.Collections; using System.Collections.Generic; -using UnityEditor; -using UnityEngine; namespace SpacetimeDB.SATS { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs b/sdks/csharp/src/SpacetimeDBClient.cs similarity index 87% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs rename to sdks/csharp/src/SpacetimeDBClient.cs index ca00f30384b..9cecb9a2d2e 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/NetworkManager.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -1,27 +1,20 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; +using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Net.WebSockets; using System.Reflection; using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; using ClientApi; -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; using Newtonsoft.Json; -using SpacetimeDB; using SpacetimeDB.SATS; -using UnityEngine; -using UnityEngine.Rendering; -using ReducerEvent = SpacetimeDB.ReducerEvent; namespace SpacetimeDB { - public class NetworkManager : MonoBehaviour + public class SpacetimeDBClient { public enum TableOp { @@ -51,7 +44,7 @@ public struct DbEvent public byte[] insertedPk; } - public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, SpacetimeDB.ReducerCallInfo dbEvent); + public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, SpacetimeDB.ReducerEventBase dbEvent); /// /// Called when a connection is established to a spacetimedb instance. @@ -86,7 +79,7 @@ public struct DbEvent /// /// Called when we receive an identity from the server /// - public event Action onIdentityReceived; + public event Action onIdentityReceived; /// /// Invoked when an event message is received or at the end of a transaction update. @@ -95,36 +88,48 @@ public struct DbEvent private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; - public static ClientCache clientDB; + public static ClientCache clientDB; public static Dictionary> reducerEventCache = new Dictionary>(); public static Dictionary> deserializeEventCache = new Dictionary>(); private Thread messageProcessThread; - public static NetworkManager instance; - - public string TokenKey - { - get { return GetTokenKey(); } + public static SpacetimeDBClient instance; + + public ILogger Logger => logger; + private ILogger logger; + + public static void CreateInstance(ILogger loggerToUse, Type reducerType) + { + if (instance == null) + { + new SpacetimeDBClient(loggerToUse, reducerType); + } + else + { + loggerToUse.LogError($"Instance already created."); + } } - protected void Awake() + protected SpacetimeDBClient(ILogger loggerToUse, Type reducerType) { if (instance != null) { - Debug.LogError($"There is more than one {GetType()}"); + loggerToUse.LogError($"There is more than one {GetType()}"); return; } instance = this; + logger = loggerToUse; + var options = new SpacetimeDB.ConnectOptions { //v1.bin.spacetimedb //v1.text.spacetimedb Protocol = "v1.bin.spacetimedb", }; - webSocket = new SpacetimeDB.WebSocket(options); + webSocket = new SpacetimeDB.WebSocket(logger, options); webSocket.OnMessage += OnMessageReceived; webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); webSocket.OnConnect += () => onConnect?.Invoke(); @@ -155,7 +160,7 @@ protected void Awake() } // cache all our reducer events by their function name - foreach (var methodInfo in typeof(SpacetimeDB.Reducer).GetMethods()) + foreach (var methodInfo in reducerType.GetMethods()) { if (methodInfo.GetCustomAttribute() is { } reducerEvent) @@ -227,7 +232,7 @@ void ProcessMessages() var table = clientDB.GetTable(tableName); if (table == null) { - Debug.LogError($"Unknown table name: {tableName}"); + logger.LogError($"Unknown table name: {tableName}"); continue; } @@ -264,7 +269,10 @@ void ProcessMessages() } var algebraicValue = AlgebraicValue.Deserialize(table.RowSchema, reader); - Debug.Assert(algebraicValue != null); + if(algebraicValue == null) + { + throw new Exception("Failed to deserialize row"); + } table.SetDecodedValue(rowPk, algebraicValue, out var obj); dbEvents.Add(new DbEvent { @@ -304,7 +312,8 @@ void ProcessMessages() continue; } - var updateEvent = new DbEvent { + var updateEvent = new DbEvent + { deletedPk = deleteEvent.deletedPk, insertedPk = insertEvent.insertedPk, op = TableOp.Update, @@ -324,7 +333,7 @@ void ProcessMessages() if (subscriptionUpdate!.TableUpdates.Any( a => a.TableRowOperations.Any(b => b.Op == TableRowOperation.Types.OperationType.Delete))) { - Debug.LogWarning( + logger.LogWarning( "We see delete events in our subscription update, this is unexpected. Likely you should update your SpacetimeDBUnitySDK."); } @@ -335,7 +344,7 @@ void ProcessMessages() .Where(a => a.Op == TableRowOperation.Types.OperationType.Insert) .Select(b => b.RowPk.ToByteArray()); var existingPks = clientTable.entries.Select(a => a.Key); - dbEvents.AddRange(existingPks.Except(newPks, new ByteArrayComparer()) + dbEvents.AddRange(existingPks.Except(newPks, new ClientCache.TableCache.ByteArrayComparer()) .Select(a => new DbEvent { deletedPk = a, @@ -358,7 +367,7 @@ void ProcessMessages() } } - private void OnDestroy() + public void Close() { connectionClosed = true; webSocket.Close(); @@ -371,10 +380,9 @@ private void OnDestroy() /// The host or IP address and the port to connect to. Example: spacetime.spacetimedb.net:3000 /// The name or address of the database to connect to /// Should websocket use SSL - public void Connect(string host, string addressOrName, bool sslEnabled = true) - { - var token = PlayerPrefs.HasKey(GetTokenKey()) ? PlayerPrefs.GetString(GetTokenKey()) : null; - + public void Connect(string token, string host, string addressOrName, bool sslEnabled = true) + { + logger.Log($"SpacetimeDBClient: Connecting to {host} {addressOrName}"); Task.Run(async () => { try @@ -385,11 +393,11 @@ public void Connect(string host, string addressOrName, bool sslEnabled = true) { if (connectionClosed) { - Debug.Log("Connection closed gracefully."); + logger.Log("Connection closed gracefully."); return; } - Debug.LogException(e); + logger.LogException(e); } }); } @@ -409,11 +417,11 @@ private void OnMessageProcessComplete(Message message, IList events) { try { - ev.table.BeforeDeleteCallback?.Invoke(oldVal, message.Event); + ev.table.BeforeDeleteCallback?.Invoke(oldVal, message.TransactionUpdate?.Event); } catch (Exception e) { - Debug.LogException(e); + logger.LogException(e); } } } @@ -471,12 +479,12 @@ private void OnMessageProcessComplete(Message message, IList events) { if (events[i].table.InsertCallback != null) { - events[i].table.InsertCallback.Invoke(newValue, message.Event); + events[i].table.InsertCallback.Invoke(newValue, message.TransactionUpdate?.Event); } } catch (Exception e) { - Debug.LogException(e); + logger.LogException(e); } try @@ -484,18 +492,18 @@ private void OnMessageProcessComplete(Message message, IList events) if (events[i].table.RowUpdatedCallback != null) { events[i].table.RowUpdatedCallback - .Invoke(tableOp, null, newValue, message.Event); + .Invoke(tableOp, null, newValue, message.TransactionUpdate?.Event); } } catch (Exception e) { - Debug.LogException(e); + logger.LogException(e); } } else { - Debug.LogError("Failed to send callback: invalid insert!"); + logger.LogError("Failed to send callback: invalid insert!"); } break; @@ -507,11 +515,11 @@ private void OnMessageProcessComplete(Message message, IList events) { try { - events[i].table.DeleteCallback.Invoke(oldValue, message.Event); + events[i].table.DeleteCallback.Invoke(oldValue, message.TransactionUpdate?.Event); } catch (Exception e) { - Debug.LogException(e); + logger.LogException(e); } } @@ -520,17 +528,17 @@ private void OnMessageProcessComplete(Message message, IList events) try { events[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, null, message.Event); + .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); } catch (Exception e) { - Debug.LogException(e); + logger.LogException(e); } } } else { - Debug.LogError("Failed to send callback: invalid delete"); + logger.LogError("Failed to send callback: invalid delete"); } break; @@ -543,12 +551,12 @@ private void OnMessageProcessComplete(Message message, IList events) { if (events[i].table.UpdateCallback != null) { - events[i].table.UpdateCallback.Invoke(oldValue, newValue, message.Event); + events[i].table.UpdateCallback.Invoke(oldValue, newValue, message.TransactionUpdate?.Event); } } catch (Exception e) { - Debug.LogException(e); + logger.LogException(e); } try @@ -556,17 +564,17 @@ private void OnMessageProcessComplete(Message message, IList events) if (events[i].table.RowUpdatedCallback != null) { events[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, null, message.Event); + .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); } } catch (Exception e) { - Debug.LogException(e); + logger.LogException(e); } } else { - Debug.LogError("Failed to send callback: invalid update"); + logger.LogError("Failed to send callback: invalid update"); } break; @@ -607,8 +615,7 @@ private void OnMessageProcessComplete(Message message, IList events) break; case Message.TypeOneofCase.IdentityToken: - onIdentityReceived?.Invoke(Identity.From(message.IdentityToken.Identity.ToByteArray())); - PlayerPrefs.SetString(GetTokenKey(), message.IdentityToken.Token); + onIdentityReceived?.Invoke(message.IdentityToken.Token, Identity.From(message.IdentityToken.Identity.ToByteArray())); break; case Message.TypeOneofCase.Event: onEvent?.Invoke(message.Event); @@ -618,28 +625,28 @@ private void OnMessageProcessComplete(Message message, IList events) private void OnMessageReceived(byte[] bytes) => _messageQueue.Add(bytes); - private string GetTokenKey() - { - var key = "spacetimedb.identity_token"; -#if UNITY_EDITOR - // Different editors need different keys - key += $" - {Application.dataPath}"; -#endif - return key; - } - - internal void InternalCallReducer(string json) + public void InternalCallReducer(string json) { + if(!webSocket.IsConnected) + { + logger.LogError("Cannot call reducer, not connected to server!"); + return; + } webSocket.Send(Encoding.ASCII.GetBytes("{ \"call\": " + json + " }")); } public void Subscribe(List queries) { + if(!webSocket.IsConnected) + { + logger.LogError("Cannot subscribe, not connected to server!"); + return; + } var json = JsonConvert.SerializeObject(queries); webSocket.Send(Encoding.ASCII.GetBytes("{ \"subscribe\": { \"query_strings\": " + json + " }}")); } - private void Update() + public void Update() { webSocket.Update(); diff --git a/sdks/csharp/src/Stubs.cs b/sdks/csharp/src/Stubs.cs new file mode 100644 index 00000000000..1a16795ce35 --- /dev/null +++ b/sdks/csharp/src/Stubs.cs @@ -0,0 +1,25 @@ +using System.Collections; +using System.Collections.Generic; + +namespace SpacetimeDB +{ + public partial class ReducerEventBase + { + public string ReducerName { get; private set; } + public ulong Timestamp { get; private set; } + public SpacetimeDB.Identity Identity { get; private set; } + public string ErrMessage { get; private set; } + public ClientApi.Event.Types.Status Status { get; private set; } + protected object Args; + + public ReducerEventBase(string reducerName, ulong timestamp, SpacetimeDB.Identity identity, string errMessage, ClientApi.Event.Types.Status status, object args) + { + ReducerName = reducerName; + Timestamp = timestamp; + Identity = identity; + ErrMessage = errMessage; + Status = status; + Args = args; + } + } +} \ No newline at end of file diff --git a/sdks/csharp/src/UnityDebugLogger.cs b/sdks/csharp/src/UnityDebugLogger.cs new file mode 100644 index 00000000000..a2a64434fcc --- /dev/null +++ b/sdks/csharp/src/UnityDebugLogger.cs @@ -0,0 +1,34 @@ +/* SpacetimeDB logging for Unity + * * This class is only used in Unity projects. + * * + */ +#if UNITY_5_3_OR_NEWER +using System; +using UnityEngine; + +namespace SpacetimeDB +{ + public class UnityDebugLogger : ILogger + { + public void Log(string message) + { + Debug.Log(message); + } + + public void LogError(string message) + { + Debug.LogError(message); + } + + public void LogException(Exception e) + { + Debug.LogException(e); + } + + public void LogWarning(string message) + { + Debug.LogWarning(message); + } + } +} +#endif \ No newline at end of file diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs b/sdks/csharp/src/Utils.cs similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/Utils.cs rename to sdks/csharp/src/Utils.cs diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs b/sdks/csharp/src/WebSocket.cs similarity index 97% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs rename to sdks/csharp/src/WebSocket.cs index 2d616f4c5c4..992c6dcc00b 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -5,7 +5,6 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using UnityEngine; namespace SpacetimeDB { @@ -66,7 +65,7 @@ public override void Execute() } } - class OnSendErrorMessage : MainThreadDispatch +class OnSendErrorMessage : MainThreadDispatch { private WebSocketSendErrorEventHandler receiver; private Exception e; @@ -127,9 +126,12 @@ public class WebSocket protected ClientWebSocket Ws; - public WebSocket(ConnectOptions options) + private ILogger _logger; + + public WebSocket(ILogger logger, ConnectOptions options) { Ws = new ClientWebSocket(); + _logger = logger; _options = options; } @@ -139,6 +141,8 @@ public WebSocket(ConnectOptions options) public event WebSocketMessageEventHandler OnMessage; public event WebSocketCloseEventHandler OnClose; + public bool IsConnected => Ws.State == WebSocketState.Open; + public async Task Connect(string auth, string host, string nameOrAddress, bool sslEnabled) { var protocol = sslEnabled ? "wss" : "ws"; @@ -169,7 +173,7 @@ public async Task Connect(string auth, string host, string nameOrAddress, bool s } catch (Exception e) { - Debug.LogException(e); + _logger.LogException(e); dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, null)); return; } @@ -273,7 +277,7 @@ private async Task ProcessSendQueue() } } catch(Exception e) - { + { senderTask = null; dispatchQueue.Enqueue(new OnSendErrorMessage(OnSendError, e)); } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs b/sdks/csharp/src/json/EnumAttribute.cs similarity index 92% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs rename to sdks/csharp/src/json/EnumAttribute.cs index 0645d6a39a6..3a66e895c2a 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumAttribute.cs +++ b/sdks/csharp/src/json/EnumAttribute.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using UnityEngine; namespace SpacetimeDB { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs b/sdks/csharp/src/json/EnumWrapper.cs similarity index 93% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs rename to sdks/csharp/src/json/EnumWrapper.cs index 169a26e7afe..6ee6fd054b6 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapper.cs +++ b/sdks/csharp/src/json/EnumWrapper.cs @@ -1,6 +1,5 @@ using System.Collections; using System.Collections.Generic; -using UnityEngine; namespace SpacetimeDB { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs b/sdks/csharp/src/json/EnumWrapperConverter.cs similarity index 97% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs rename to sdks/csharp/src/json/EnumWrapperConverter.cs index 839db9a6229..a199153d0ec 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/EnumWrapperConverter.cs +++ b/sdks/csharp/src/json/EnumWrapperConverter.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using Namespace; using Newtonsoft.Json; -using UnityEngine; namespace SpacetimeDB { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs b/sdks/csharp/src/json/JsonContractResolver.cs similarity index 93% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs rename to sdks/csharp/src/json/JsonContractResolver.cs index 678ba6f8d31..28853740bf8 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/JsonContractResolver.cs +++ b/sdks/csharp/src/json/JsonContractResolver.cs @@ -4,7 +4,6 @@ using System; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -using UnityEngine; namespace SpacetimeDB { @@ -31,7 +30,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s } } - public class EnumConverter : JsonConverter +public class EnumConverter : JsonConverter { public override bool CanConvert(Type objectType) => true; @@ -50,7 +49,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s } } - public class JsonContractResolver : DefaultContractResolver +public class JsonContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { @@ -61,6 +60,7 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ property.Converter = new SomeConverter(); } else if (member.GetCustomAttribute() != null) { + property.Converter = new EnumConverter(); } diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs b/sdks/csharp/src/json/SomeAttribute.cs similarity index 92% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs rename to sdks/csharp/src/json/SomeAttribute.cs index b8bdd44c7d3..77bbc91869e 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeAttribute.cs +++ b/sdks/csharp/src/json/SomeAttribute.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using UnityEngine; namespace SpacetimeDB { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs b/sdks/csharp/src/json/SomeWrapper.cs similarity index 92% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs rename to sdks/csharp/src/json/SomeWrapper.cs index 8db5f0258fe..a7589344f3c 100644 --- a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapper.cs +++ b/sdks/csharp/src/json/SomeWrapper.cs @@ -1,6 +1,5 @@ using System.Collections; using System.Collections.Generic; -using UnityEngine; namespace Namespace { diff --git a/sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs b/sdks/csharp/src/json/SomeWrapperConverter.cs similarity index 100% rename from sdks/csharp/Assets/SpacetimeDB/Scripts/json/SomeWrapperConverter.cs rename to sdks/csharp/src/json/SomeWrapperConverter.cs diff --git a/sdks/csharp/upload.sh b/sdks/csharp/upload.sh deleted file mode 100755 index b6da31dccee..00000000000 --- a/sdks/csharp/upload.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -usage() { - echo "Usage: upload.sh " -} - -if [ "$#" != 2 ] ; then - usage - exit 1 -fi - -if [ ! -f "$1" ] ; then - usage - echo "File not found: $1" - exit -fi - -echo "Make sure you have used \"export.sh\" to regenerate the SpacetimeDBUnitySDK." -echo -echo "We will be uploading this SDK to $2" -echo "Your current branch is $(git rev-parse --abbrev-ref HEAD)" -echo -echo "If everything looks correct, press [Enter] now to continue." -read -rp "" - -scp -oStrictHostKeyChecking=no -i "$1" "SpacetimeDBUnitySDK.unitypackage" "root@${2}:/var/www/sdk/SpacetimeDBUnitySDK.unitypackage" -ssh -oStrictHostKeyChecking=no -i "$1" "root@${2}" "chown -R jenkins:jenkins /var/www/sdk" -echo "Upload success." From bebd5db60e13d78b7ea6fbfddacf71bb46c0aed2 Mon Sep 17 00:00:00 2001 From: Derek Brinkmann Date: Wed, 5 Jul 2023 08:58:15 -0400 Subject: [PATCH 041/223] Rename ILogger class to ISpacetimeDBLogger to avoid some annoying naming conflicts. --- sdks/csharp/src/ConsoleLogger.cs | 2 +- sdks/csharp/src/ConsoleLogger.cs.bak | 60 +++++++++++++++++++ .../src/{ILogger.cs => ISpacetimeDBLogger.cs} | 5 +- sdks/csharp/src/SpacetimeDBClient.cs | 8 +-- sdks/csharp/src/UnityDebugLogger.cs | 2 +- sdks/csharp/src/WebSocket.cs | 4 +- 6 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 sdks/csharp/src/ConsoleLogger.cs.bak rename sdks/csharp/src/{ILogger.cs => ISpacetimeDBLogger.cs} (76%) diff --git a/sdks/csharp/src/ConsoleLogger.cs b/sdks/csharp/src/ConsoleLogger.cs index aa22c90d8e9..013059aa68d 100644 --- a/sdks/csharp/src/ConsoleLogger.cs +++ b/sdks/csharp/src/ConsoleLogger.cs @@ -6,7 +6,7 @@ namespace SpacetimeDB { - public class ConsoleLogger : ILogger + public class ConsoleLogger : ISpacetimeDBLogger { [Flags] public enum LogLevel diff --git a/sdks/csharp/src/ConsoleLogger.cs.bak b/sdks/csharp/src/ConsoleLogger.cs.bak new file mode 100644 index 00000000000..aa22c90d8e9 --- /dev/null +++ b/sdks/csharp/src/ConsoleLogger.cs.bak @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SpacetimeDB +{ + public class ConsoleLogger : ILogger + { + [Flags] + public enum LogLevel + { + None = 0, + Debug = 1, + Warning = 2, + Error = 4, + Exception = 8, + All = Debug | Warning | Error | Exception + } + LogLevel _logLevel; + + public ConsoleLogger(LogLevel logLevel = LogLevel.All) + { + _logLevel = logLevel; + } + + public void Log(string message) + { + if (_logLevel.HasFlag(LogLevel.Debug)) + { + Console.WriteLine(message); + } + } + + public void LogError(string message) + { + if (_logLevel.HasFlag(LogLevel.Error)) + { + Console.WriteLine($"Error: {message}"); + } + } + + public void LogException(Exception e) + { + if (_logLevel.HasFlag(LogLevel.Exception)) + { + Console.WriteLine($"Exception: {e.Message}"); + } + } + + public void LogWarning(string message) + { + if (_logLevel.HasFlag(LogLevel.Warning)) + { + Console.WriteLine($"Warning: {message}"); + } + } + } +} diff --git a/sdks/csharp/src/ILogger.cs b/sdks/csharp/src/ISpacetimeDBLogger.cs similarity index 76% rename from sdks/csharp/src/ILogger.cs rename to sdks/csharp/src/ISpacetimeDBLogger.cs index 9a29e298932..7689e925ccf 100644 --- a/sdks/csharp/src/ILogger.cs +++ b/sdks/csharp/src/ISpacetimeDBLogger.cs @@ -3,13 +3,10 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -#if UNITY_5_3_OR_NEWER -using UnityEngine; -#endif namespace SpacetimeDB { - public interface ILogger + public interface ISpacetimeDBLogger { void Log(string message); void LogError(string message); diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 9cecb9a2d2e..fb27675b7e0 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -96,10 +96,10 @@ public struct DbEvent public static SpacetimeDBClient instance; - public ILogger Logger => logger; - private ILogger logger; + public ISpacetimeDBLogger Logger => logger; + private ISpacetimeDBLogger logger; - public static void CreateInstance(ILogger loggerToUse, Type reducerType) + public static void CreateInstance(ISpacetimeDBLogger loggerToUse, Type reducerType) { if (instance == null) { @@ -111,7 +111,7 @@ public static void CreateInstance(ILogger loggerToUse, Type reducerType) } } - protected SpacetimeDBClient(ILogger loggerToUse, Type reducerType) + protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse, Type reducerType) { if (instance != null) { diff --git a/sdks/csharp/src/UnityDebugLogger.cs b/sdks/csharp/src/UnityDebugLogger.cs index a2a64434fcc..cc31dd45e79 100644 --- a/sdks/csharp/src/UnityDebugLogger.cs +++ b/sdks/csharp/src/UnityDebugLogger.cs @@ -8,7 +8,7 @@ namespace SpacetimeDB { - public class UnityDebugLogger : ILogger + public class UnityDebugLogger : ISpacetimeDBLogger { public void Log(string message) { diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 992c6dcc00b..8d81172d375 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -126,9 +126,9 @@ public class WebSocket protected ClientWebSocket Ws; - private ILogger _logger; + private ISpacetimeDBLogger _logger; - public WebSocket(ILogger logger, ConnectOptions options) + public WebSocket(ISpacetimeDBLogger logger, ConnectOptions options) { Ws = new ClientWebSocket(); _logger = logger; From de4ea64c6f4de6f6056451ffdd1aed6a5f40eb9a Mon Sep 17 00:00:00 2001 From: Derek Brinkmann Date: Wed, 5 Jul 2023 17:14:45 -0400 Subject: [PATCH 042/223] search for reducer type using reflection instead of passing in nuget package manager files remove bak file --- sdks/csharp/README.md | 19 ++++++++ sdks/csharp/SpacetimeDBCSharpSDK.csproj | 31 ++++++++++++ sdks/csharp/logo.png | Bin 0 -> 3485 bytes sdks/csharp/src/ConsoleLogger.cs.bak | 60 ------------------------ sdks/csharp/src/NetworkManager.cs | 2 +- sdks/csharp/src/SpacetimeDBClient.cs | 42 +++++++++++++++-- 6 files changed, 90 insertions(+), 64 deletions(-) create mode 100644 sdks/csharp/README.md create mode 100644 sdks/csharp/logo.png delete mode 100644 sdks/csharp/src/ConsoleLogger.cs.bak diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md new file mode 100644 index 00000000000..c43fce5c41b --- /dev/null +++ b/sdks/csharp/README.md @@ -0,0 +1,19 @@ +# SpaceTimeDB SDK for C# + +The SpacetimeDB SDK is a software development kit (SDK) designed to simplify the interaction with SpacetimeDB server modules. + +## Key Features + +### Connection Management + +The SDK simplifies the process of establishing and managing connections to the SpacetimeDB module. Developers can establish secure WebSocket connections, enabling real-time communication with the module. + +### Local Client Cache + +By subscribing to a set of queries, the SDK will keep a local cache of rows that match the subscribed queries. SpacetimeDB generates C# files that allow you to iterate throught these tables and filter on specific columns. + +### Transaction and Row Update Events + +Register for transaction and row update events. + +Full documentation can be found on the [SpacetimeDB](spacetimedb.com) website. \ No newline at end of file diff --git a/sdks/csharp/SpacetimeDBCSharpSDK.csproj b/sdks/csharp/SpacetimeDBCSharpSDK.csproj index 04e55ba1342..736b51e88f2 100644 --- a/sdks/csharp/SpacetimeDBCSharpSDK.csproj +++ b/sdks/csharp/SpacetimeDBCSharpSDK.csproj @@ -4,11 +4,42 @@ net7.0 enable enable + True + spacetimedbsdk + SpacetimeDB SDK + derek_clockwork + Clockwork Labs + SpacetimeDB + The SpacetimeDB SDK is a software development kit (SDK) designed to simplify the interaction with SpacetimeDB server modules. + 2023 + http://spacetimedb.com + logo.png + README.md + https://github.com/clockworklabs/SpacetimeDBCSharpSDK + 0.5.0 + 0.5.0 + + + + + + + + + True + \ + + + True + \ + + + diff --git a/sdks/csharp/logo.png b/sdks/csharp/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9500cc4bcb4cb12a7072e0c81f4e64ca48de7f5c GIT binary patch literal 3485 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 eM2nH5Zu1M#PoFo5|sHwrTqtB+-9Tz literal 0 HcmV?d00001 diff --git a/sdks/csharp/src/ConsoleLogger.cs.bak b/sdks/csharp/src/ConsoleLogger.cs.bak deleted file mode 100644 index aa22c90d8e9..00000000000 --- a/sdks/csharp/src/ConsoleLogger.cs.bak +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SpacetimeDB -{ - public class ConsoleLogger : ILogger - { - [Flags] - public enum LogLevel - { - None = 0, - Debug = 1, - Warning = 2, - Error = 4, - Exception = 8, - All = Debug | Warning | Error | Exception - } - LogLevel _logLevel; - - public ConsoleLogger(LogLevel logLevel = LogLevel.All) - { - _logLevel = logLevel; - } - - public void Log(string message) - { - if (_logLevel.HasFlag(LogLevel.Debug)) - { - Console.WriteLine(message); - } - } - - public void LogError(string message) - { - if (_logLevel.HasFlag(LogLevel.Error)) - { - Console.WriteLine($"Error: {message}"); - } - } - - public void LogException(Exception e) - { - if (_logLevel.HasFlag(LogLevel.Exception)) - { - Console.WriteLine($"Exception: {e.Message}"); - } - } - - public void LogWarning(string message) - { - if (_logLevel.HasFlag(LogLevel.Warning)) - { - Console.WriteLine($"Warning: {message}"); - } - } - } -} diff --git a/sdks/csharp/src/NetworkManager.cs b/sdks/csharp/src/NetworkManager.cs index 06cc3e3dbbc..8e71b5f22a5 100644 --- a/sdks/csharp/src/NetworkManager.cs +++ b/sdks/csharp/src/NetworkManager.cs @@ -34,7 +34,7 @@ public class NetworkManager : MonoBehaviour protected void Awake() { // If you get a compile error on `Reducer`, that means you need to run the SpacetimeDB CLI generate command - SpacetimeDBClient.CreateInstance(new UnityDebugLogger(), typeof(Reducer)); + SpacetimeDBClient.CreateInstance(new UnityDebugLogger()); } private void OnDestroy() diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index fb27675b7e0..17d01abcf9f 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -99,11 +99,11 @@ public struct DbEvent public ISpacetimeDBLogger Logger => logger; private ISpacetimeDBLogger logger; - public static void CreateInstance(ISpacetimeDBLogger loggerToUse, Type reducerType) + public static void CreateInstance(ISpacetimeDBLogger loggerToUse) { if (instance == null) { - new SpacetimeDBClient(loggerToUse, reducerType); + new SpacetimeDBClient(loggerToUse); } else { @@ -111,7 +111,35 @@ public static void CreateInstance(ISpacetimeDBLogger loggerToUse, Type reducerTy } } - protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse, Type reducerType) + public Type FindReducerType() + { + // Get all loaded assemblies + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + // Iterate over each assembly and search for the type + foreach (Assembly assembly in assemblies) + { + // Get all types in the assembly + Type[] types = assembly.GetTypes(); + + // Search for the type by name and namespace + Type targetType = types.FirstOrDefault(t => + t.Name == "Reducer" && + t.Namespace == "SpacetimeDB"); + + // If the type is found, return it + if (targetType != null) + { + return targetType; + } + } + + // If the type is not found in any assembly, return null or throw an exception + return null; + } + + + protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) { if (instance != null) { @@ -159,6 +187,9 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse, Type reducerType) a => { return conversionFunc!.Invoke(null, new object[] { a }); }); } + var reducerType = FindReducerType(); + if (reducerType != null) + { // cache all our reducer events by their function name foreach (var methodInfo in reducerType.GetMethods()) { @@ -173,6 +204,11 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse, Type reducerType) { deserializeEventCache.Add(deserializeEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); } + } + } + else + { + loggerToUse.LogError($"Could not find reducer type. Have you run spacetime generate?"); } messageProcessThread = new Thread(ProcessMessages); From 76cd6ee0058b37186ce34f5c00c18676f5629cd0 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Wed, 12 Jul 2023 07:55:17 -0500 Subject: [PATCH 043/223] Fixed serialization issue + added jetbrains IDE files to gitignore (#37) Co-authored-by: Boppy --- sdks/csharp/.gitignore | 5 ++++- sdks/csharp/src/json/EnumWrapperConverter.cs | 2 +- sdks/csharp/src/json/JsonContractResolver.cs | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sdks/csharp/.gitignore b/sdks/csharp/.gitignore index 644de291094..5a51aeffefd 100644 --- a/sdks/csharp/.gitignore +++ b/sdks/csharp/.gitignore @@ -131,4 +131,7 @@ $RECYCLE.BIN/ # Mac desktop service store files .DS_Store -_NCrunch* \ No newline at end of file +_NCrunch* + +# JetBrains Ignore +.idea/ diff --git a/sdks/csharp/src/json/EnumWrapperConverter.cs b/sdks/csharp/src/json/EnumWrapperConverter.cs index a199153d0ec..1074c7f5d4f 100644 --- a/sdks/csharp/src/json/EnumWrapperConverter.cs +++ b/sdks/csharp/src/json/EnumWrapperConverter.cs @@ -24,7 +24,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s { writer.WriteStartObject(); writer.WritePropertyName(value.ToString()); - writer.WriteRaw("{}"); + writer.WriteRawValue("{}"); writer.WriteEndObject(); } diff --git a/sdks/csharp/src/json/JsonContractResolver.cs b/sdks/csharp/src/json/JsonContractResolver.cs index 28853740bf8..1b6532f9fa6 100644 --- a/sdks/csharp/src/json/JsonContractResolver.cs +++ b/sdks/csharp/src/json/JsonContractResolver.cs @@ -30,7 +30,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s } } -public class EnumConverter : JsonConverter + public class EnumConverter : JsonConverter { public override bool CanConvert(Type objectType) => true; @@ -44,12 +44,12 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s { writer.WriteStartObject(); writer.WritePropertyName(value.ToString()); - writer.WriteRaw("{}"); + writer.WriteRawValue("{}"); writer.WriteEndObject(); } } -public class JsonContractResolver : DefaultContractResolver + public class JsonContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { From eee513186aa6a9d17610f4e7d0bb83ba2dcd96b6 Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Tue, 18 Jul 2023 12:33:11 -0400 Subject: [PATCH 044/223] Fix close and improve onConnectError message (#36) * Fix close not stopping message thread Add error message to onConnectError Add more context to "NotAWebSocket" error * Remove unnecesary while loop * Clear isclosing flag on Connect --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/src/SpacetimeDBClient.cs | 58 ++++++++++++++++++---------- sdks/csharp/src/WebSocket.cs | 28 +++++++++----- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 17d01abcf9f..948562f9356 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -1,17 +1,17 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; +using System; using System.Linq; +using System.Collections.Generic; +using System.Collections.Concurrent; using System.Net.WebSockets; using System.Reflection; -using System.Text; -using System.Threading; -using System.Threading.Tasks; +using System.Text; using ClientApi; using Newtonsoft.Json; using SpacetimeDB.SATS; - +using System.Threading; +using System.IO; +using System.Threading.Tasks; + namespace SpacetimeDB { public class SpacetimeDBClient @@ -54,7 +54,7 @@ public struct DbEvent /// /// Called when a connection attempt fails. /// - public event Action onConnectError; + public event Action onConnectError; /// /// Called when an exception occurs when sending a message. @@ -92,6 +92,7 @@ public struct DbEvent public static Dictionary> reducerEventCache = new Dictionary>(); public static Dictionary> deserializeEventCache = new Dictionary>(); + private bool isClosing; private Thread messageProcessThread; public static SpacetimeDBClient instance; @@ -161,7 +162,7 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) webSocket.OnMessage += OnMessageReceived; webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); webSocket.OnConnect += () => onConnect?.Invoke(); - webSocket.OnConnectError += a => onConnectError?.Invoke(a); + webSocket.OnConnectError += (a,b) => onConnectError?.Invoke(a,b); webSocket.OnSendError += a => onSendError?.Invoke(a); clientDB = new ClientCache(); @@ -211,6 +212,8 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) loggerToUse.LogError($"Could not find reducer type. Have you run spacetime generate?"); } + _cancellationToken = _cancellationTokenSource.Token; + messageProcessThread = new Thread(ProcessMessages); messageProcessThread.Start(); } @@ -222,21 +225,32 @@ struct ProcessedMessage } private readonly BlockingCollection _messageQueue = new BlockingCollection(new ConcurrentQueue()); - private readonly BlockingCollection _nextMessageQueue = new BlockingCollection(new ConcurrentQueue()); + private readonly BlockingCollection _nextMessageQueue = new BlockingCollection(new ConcurrentQueue()); + + CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); + CancellationToken _cancellationToken; void ProcessMessages() { - while (true) + while (!isClosing) { - var bytes = _messageQueue.Take(); + try + { + var bytes = _messageQueue.Take(_cancellationToken); - var (m, events) = PreProcessMessage(bytes); - var processedMessage = new ProcessedMessage - { - message = m, - events = events, - }; - _nextMessageQueue.Add(processedMessage); + var (m, events) = PreProcessMessage(bytes); + var processedMessage = new ProcessedMessage + { + message = m, + events = events, + }; + _nextMessageQueue.Add(processedMessage); + } + catch(OperationCanceledException) + { + // Normal shutdown + return; + } } (Message, List) PreProcessMessage(byte[] bytes) @@ -405,8 +419,10 @@ void ProcessMessages() public void Close() { + isClosing = true; connectionClosed = true; webSocket.Close(); + _cancellationTokenSource.Cancel(); webSocket = null; } @@ -418,6 +434,8 @@ public void Close() /// Should websocket use SSL public void Connect(string token, string host, string addressOrName, bool sslEnabled = true) { + isClosing = false; + logger.Log($"SpacetimeDBClient: Connecting to {host} {addressOrName}"); Task.Run(async () => { diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 8d81172d375..a9d91d31aec 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -52,16 +52,18 @@ class OnConnectErrorMessage : MainThreadDispatch { private WebSocketConnectErrorEventHandler receiver; private WebSocketError? error; + private string? errorMsg; - public OnConnectErrorMessage(WebSocketConnectErrorEventHandler receiver, WebSocketError? error) + public OnConnectErrorMessage(WebSocketConnectErrorEventHandler receiver, WebSocketError? error, string? errorMsg) { this.receiver = receiver; this.error = error; + this.errorMsg = errorMsg; } public override void Execute() { - receiver.Invoke(error); + receiver.Invoke(error, errorMsg); } } @@ -105,7 +107,7 @@ public override void Execute() public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); - public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error); + public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error, string? message); public delegate void WebSocketSendErrorEventHandler(Exception e); public struct ConnectOptions @@ -141,7 +143,7 @@ public WebSocket(ISpacetimeDBLogger logger, ConnectOptions options) public event WebSocketMessageEventHandler OnMessage; public event WebSocketCloseEventHandler OnClose; - public bool IsConnected => Ws.State == WebSocketState.Open; + public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } public async Task Connect(string auth, string host, string nameOrAddress, bool sslEnabled) { @@ -168,13 +170,19 @@ public async Task Connect(string auth, string host, string nameOrAddress, bool s } catch (WebSocketException ex) { - dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode)); + string message = ex.Message; + if(ex.WebSocketErrorCode == WebSocketError.NotAWebSocket) + { + // not a websocket happens when there is no module published under the address specified + message = $"{message} Did you forget to publish your module?"; + } + dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode, message)); return; } catch (Exception e) { _logger.LogException(e); - dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, null)); + dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, null, e.Message)); return; } @@ -186,8 +194,11 @@ public async Task Connect(string auth, string host, string nameOrAddress, bool s CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { - await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, - CancellationToken.None); + if (Ws.State != WebSocketState.Closed) + { + await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, + CancellationToken.None); + } dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, receiveResult.CloseStatus, null)); return; } @@ -227,7 +238,6 @@ await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure, string reason = null) { Ws?.CloseAsync(code, "Disconnecting normally.", CancellationToken.None); - Ws = null; return Task.CompletedTask; } From a0f8c48e8748546d735814adff1fc6d73b769714 Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Tue, 18 Jul 2023 12:52:50 -0400 Subject: [PATCH 045/223] Add optional component to handle saving auth token (#39) * Add optional component to handle saving auth token to local storage. By default it saves to your user dir * Fixes for naming collisions --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/SpacetimeDBCSharpSDK.csproj | 3 + sdks/csharp/src/AuthToken.cs | 115 ++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 sdks/csharp/src/AuthToken.cs diff --git a/sdks/csharp/SpacetimeDBCSharpSDK.csproj b/sdks/csharp/SpacetimeDBCSharpSDK.csproj index 736b51e88f2..e3112f7946f 100644 --- a/sdks/csharp/SpacetimeDBCSharpSDK.csproj +++ b/sdks/csharp/SpacetimeDBCSharpSDK.csproj @@ -21,8 +21,11 @@ + + + diff --git a/sdks/csharp/src/AuthToken.cs b/sdks/csharp/src/AuthToken.cs new file mode 100644 index 00000000000..1f5cce339b6 --- /dev/null +++ b/sdks/csharp/src/AuthToken.cs @@ -0,0 +1,115 @@ +/* This is an optional helper class to store your auth token in local storage + * + Example: + + AuthToken.Init(".my_app_name"); + + SpacetimeDBClient.CreateInstance(new ConsoleLogger()); + + SpacetimeDBClient.instance.onIdentityReceived += (token, identity) => + { + AuthToken.SaveToken(token); + + ... + }; + + SpacetimeDBClient.instance.Connect(AuthToken.Token, "localhost:3000", "basicchat", false); + */ +#if !UNITY_5_3_OR_NEWER +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SpacetimeDB +{ + public static class AuthToken + { + private static string? settingsPath = null; + private static string? token = null; + + /// + /// Initializes the AuthToken class. This must be called before any other methods. + /// + /// The folder to store the config file in. Default is ".spacetime_csharp_sdk". + /// The name of the config file. Default is "settings.ini". + /// The root folder to store the config file in. Default is the user's home directory. + /// + public static void Init(string configFolder = ".spacetime_csharp_sdk", string configFile = "settings.ini", string? configRoot = null) + { + if (configRoot == null) + { + configRoot = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + } + + if (Environment.GetCommandLineArgs().Any(arg => arg == "--client")) + { + int clientIndex = Array.FindIndex(Environment.GetCommandLineArgs(), arg => arg == "--client"); + var configFileParts = configFile.Split("."); + configFile = $"{configFileParts[0]}_{Environment.GetCommandLineArgs()[clientIndex + 1]}.{configFileParts[1]}"; + } + + settingsPath = Path.Combine(configRoot, configFolder, configFile); + + if (File.Exists(settingsPath)) + { + foreach (string line in File.ReadAllLines(settingsPath)) + { + if (line.StartsWith("auth_token=")) + { + token = line.Substring("auth_token=".Length); + break; + } + } + } + } + + /// + /// This is the auth token that was saved to local storage. Null if not never saved. + /// When you specify null to the SpacetimeDBClient, SpacetimeDB will generate a new identity for you. + /// + public static string? Token + { + get + { + if (settingsPath == null) + { + throw new Exception("Token not initialized. Call AuthToken.Init() first."); + } + return token; + } + } + + /// + /// Save the auth token to local storage. + /// SpacetimeDBClient provides this token to you in the onIdentityReceived callback. + /// + public static void SaveToken(string token) + { + Directory.CreateDirectory(Path.GetDirectoryName(settingsPath)!); + if (File.Exists(settingsPath)) + { + List lines = File.ReadAllLines(settingsPath).ToList(); + bool found = false; + for (int i = 0; i < lines.Count; i++) + { + if (lines[i].StartsWith("auth_token=")) + { + lines[i] = "auth_token=" + token; + found = true; + } + } + if (!found) + { + lines.Add("auth_token=" + token); + } + File.WriteAllLines(settingsPath, lines); + } + else + { + File.WriteAllText(settingsPath, "auth_token=" + token); + } + } + } +} +#endif \ No newline at end of file From 499014940e51c5acc9a87d51d86030f5c7ce8177 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Tue, 18 Jul 2023 13:01:08 -0500 Subject: [PATCH 046/223] Fix Typeo (#40) --- sdks/csharp/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index c43fce5c41b..111635efdfa 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -1,4 +1,4 @@ -# SpaceTimeDB SDK for C# +# SpacetimeDB SDK for C# The SpacetimeDB SDK is a software development kit (SDK) designed to simplify the interaction with SpacetimeDB server modules. @@ -16,4 +16,4 @@ By subscribing to a set of queries, the SDK will keep a local cache of rows that Register for transaction and row update events. -Full documentation can be found on the [SpacetimeDB](spacetimedb.com) website. \ No newline at end of file +Full documentation can be found on the [SpacetimeDB](spacetimedb.com) website. From 134834a627e99f6ba2b43e47fd677686c0fea836 Mon Sep 17 00:00:00 2001 From: Alessandro Asoni Date: Mon, 31 Jul 2023 18:12:12 +0200 Subject: [PATCH 047/223] Use correct hashcode for identity (#45) * Use correct hashcode for Identity * Sneak a tostring fix into this branch --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/src/Identity.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sdks/csharp/src/Identity.cs b/sdks/csharp/src/Identity.cs index a703979b8c3..90a37cd4b62 100644 --- a/sdks/csharp/src/Identity.cs +++ b/sdks/csharp/src/Identity.cs @@ -68,7 +68,12 @@ public override int GetHashCode() throw new InvalidOperationException("Cannot hash on null bytes."); } - return bytes.GetHashCode(); + return BitConverter.ToInt32(bytes, 0); + } + + public override string ToString() + { + return string.Concat(bytes.Select(b => b.ToString("x2"))); } } } From 9b21d40c1b0aaf60408beb4ef2819f5d1536e43e Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:22:38 -0400 Subject: [PATCH 048/223] generate types to SpacetimeDB.Types namespace (#41) * generate types to SpacetimeDB.Types namespace * Fix the way we look for Reducer class --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/src/ReducerExtensions.cs | 4 ++++ sdks/csharp/src/SpacetimeDBClient.cs | 15 +++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sdks/csharp/src/ReducerExtensions.cs b/sdks/csharp/src/ReducerExtensions.cs index cca7f2849dd..a86e364963a 100644 --- a/sdks/csharp/src/ReducerExtensions.cs +++ b/sdks/csharp/src/ReducerExtensions.cs @@ -2,6 +2,10 @@ namespace SpacetimeDB { + public class ReducerClassAttribute : Attribute + { + } + public class ReducerCallbackAttribute : Attribute { public string FunctionName { get; set; } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 948562f9356..54db28147fa 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -123,16 +123,15 @@ public Type FindReducerType() // Get all types in the assembly Type[] types = assembly.GetTypes(); - // Search for the type by name and namespace - Type targetType = types.FirstOrDefault(t => - t.Name == "Reducer" && - t.Namespace == "SpacetimeDB"); - - // If the type is found, return it - if (targetType != null) + // Search for the class with the attribute ReducerClass + foreach (Type type in types) { - return targetType; + if (type.GetCustomAttribute() != null) + { + return type; + } } + } // If the type is not found in any assembly, return null or throw an exception From 3bc803b7ff9eec0b247858f807f75f1a4c7c3395 Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Tue, 1 Aug 2023 12:29:37 -0400 Subject: [PATCH 049/223] Fix using Identity as Primary Key (#43) Co-authored-by: Derek Brinkmann --- sdks/csharp/src/SATS/AlgebraicValue.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sdks/csharp/src/SATS/AlgebraicValue.cs b/sdks/csharp/src/SATS/AlgebraicValue.cs index 0f4b1e8e8c5..1aa15a1bb84 100644 --- a/sdks/csharp/src/SATS/AlgebraicValue.cs +++ b/sdks/csharp/src/SATS/AlgebraicValue.cs @@ -246,6 +246,28 @@ public static bool Compare(BuiltinType t, BuiltinValue v1, BuiltinValue v2) case BuiltinType.Type.String: return v1.AsString() == v2.AsString(); case BuiltinType.Type.Array: + if (t.arrayType.type == AlgebraicType.Type.Builtin && + t.arrayType.builtin.type == BuiltinType.Type.U8) + { + var arr1 = v1.AsBytes(); + var arr2 = v2.AsBytes(); + + if (arr1.Length != arr2.Length) + { + return false; + } + + for (var i = 0; i < arr1.Length; i++) + { + if (arr1[i] != arr2[i]) + { + return false; + } + } + + return true; + } + var list1 = v1.AsArray(); var list2 = v2.AsArray(); if (list1.Count != list2.Count) From c7dbe3540cc11ef05404c6fe12f026a5c4d23a8e Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Tue, 1 Aug 2023 21:43:09 -0500 Subject: [PATCH 050/223] Created PR Template (#38) * Added PR Template * Changed headers a bit --------- Co-authored-by: Boppy --- sdks/csharp/.github/pull_request_template.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 sdks/csharp/.github/pull_request_template.md diff --git a/sdks/csharp/.github/pull_request_template.md b/sdks/csharp/.github/pull_request_template.md new file mode 100644 index 00000000000..88fcaef9487 --- /dev/null +++ b/sdks/csharp/.github/pull_request_template.md @@ -0,0 +1,12 @@ +## Description of Changes +*Describe what has been changed, any new features or bug fixes* + +## API + + - [ ] This is an API breaking change to the SDK + +*If the API is breaking, please state below what will break* + + +## Requires SpacetimeDB PRs +*List any PRs here that are required for this SDK change to work* From 1a95b387db0f4494ad0262b88ca502cbb82e606b Mon Sep 17 00:00:00 2001 From: Alessandro Asoni Date: Wed, 2 Aug 2023 10:31:11 +0200 Subject: [PATCH 051/223] Performance improvement for Del/Ins -> Update conversion (#47) * generate types to SpacetimeDB.Types namespace * Fix the way we look for Reducer class * Fix using Identity as Primary Key * Performance improvement for Del/Ins -> Update conversion * Fix * work * fixes * Remove accidental commit * Fix indentation --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/src/ClientCache.cs | 16 + sdks/csharp/src/SATS/AlgebraicValue.cs | 55 ++- sdks/csharp/src/SpacetimeDBClient.cs | 447 +++++++++++++------------ 3 files changed, 291 insertions(+), 227 deletions(-) diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index fa9c76f8b20..3f0343bc0f3 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -62,6 +62,8 @@ public Type ClientTableType // TODO: Consider renaming this one, this kind of implies that its a callback for the Update operation public Action RowUpdatedCallback; public Func ComparePrimaryKeyFunc; + public Func GetPrimaryKeyValueFunc; + public Func GetPrimaryKeyTypeFunc; public string Name { @@ -90,6 +92,10 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func)); ComparePrimaryKeyFunc = (Func)clientTableType.GetMethod("ComparePrimaryKey", BindingFlags.Static | BindingFlags.Public) ?.CreateDelegate(typeof(Func)); + GetPrimaryKeyValueFunc = (Func)clientTableType.GetMethod("GetPrimaryKeyValue", BindingFlags.Static | BindingFlags.Public) + ?.CreateDelegate(typeof(Func)); + GetPrimaryKeyTypeFunc = (Func)clientTableType.GetMethod("GetPrimaryKeyType", BindingFlags.Static | BindingFlags.Public) + ?.CreateDelegate(typeof(Func)); entries = new Dictionary(new ByteArrayComparer()); decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); } @@ -212,6 +218,16 @@ public bool ComparePrimaryKey(AlgebraicValue v1, AlgebraicValue v2) return (bool)ComparePrimaryKeyFunc.Invoke(rowSchema, v1, v2); } + public AlgebraicValue GetPrimaryKeyValue(AlgebraicValue row) + { + return GetPrimaryKeyValueFunc != null ? GetPrimaryKeyValueFunc.Invoke(row) : null; + } + + public AlgebraicType GetPrimaryKeyType(AlgebraicType row) + { + return GetPrimaryKeyTypeFunc != null ? GetPrimaryKeyTypeFunc.Invoke(row) : null; + } + public bool ComparePrimaryKey(byte[] rowPk1, byte[] rowPk2) { if (!decodedValues.TryGetValue(rowPk1, out var v1)) diff --git a/sdks/csharp/src/SATS/AlgebraicValue.cs b/sdks/csharp/src/SATS/AlgebraicValue.cs index 1aa15a1bb84..9d78de35712 100644 --- a/sdks/csharp/src/SATS/AlgebraicValue.cs +++ b/sdks/csharp/src/SATS/AlgebraicValue.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using System.IO; @@ -25,7 +26,7 @@ public struct BuiltinValue public string AsString() => (string)value; public List AsArray() => (List)value; public Dictionary AsMap() => (Dictionary)value; - + public static BuiltinValue CreateBool(bool value) => new BuiltinValue { value = value }; public static BuiltinValue CreateI8(sbyte value) => new BuiltinValue { value = value }; public static BuiltinValue CreateU8(byte value) => new BuiltinValue { value = value }; @@ -198,18 +199,18 @@ byte[] ReadByteArray() return CreateArray(arrayResult); case BuiltinType.Type.Map: - { - var len = reader.ReadUInt32(); - var mapResult = new Dictionary(); - for (var x = 0; x < len; x++) { - var key = AlgebraicValue.Deserialize(type.mapType.keyType, reader); - var value = AlgebraicValue.Deserialize(type.mapType.valueType, reader); - mapResult.Add(key, value); - } + var len = reader.ReadUInt32(); + var mapResult = new Dictionary(); + for (var x = 0; x < len; x++) + { + var key = AlgebraicValue.Deserialize(type.mapType.keyType, reader); + var value = AlgebraicValue.Deserialize(type.mapType.valueType, reader); + mapResult.Add(key, value); + } - return CreateMap(mapResult); - } + return CreateMap(mapResult); + } default: throw new NotImplementedException(); } @@ -367,7 +368,7 @@ public static bool Compare(ProductType type, ProductValue v1, ProductValue v2) for (var i = 0; i < type.elements.Count; i++) { - if(!AlgebraicValue.Compare(type.elements[i].algebraicType, v1.elements[i], v2.elements[i])) + if (!AlgebraicValue.Compare(type.elements[i].algebraicType, v1.elements[i], v2.elements[i])) { return false; } @@ -442,7 +443,7 @@ public static bool Compare(AlgebraicType t, AlgebraicValue v1, AlgebraicValue v2 throw new NotImplementedException(); } } - + public static AlgebraicValue Deserialize(AlgebraicType type, BinaryReader reader) { switch (type.type) @@ -475,5 +476,33 @@ public void Serialize(AlgebraicType type, BinaryWriter writer) throw new NotImplementedException(); } } + + public class AlgebraicValueComparer : IEqualityComparer + { + private AlgebraicType type; + public AlgebraicValueComparer(AlgebraicType type) + { + this.type = type; + } + + public bool Equals(AlgebraicValue l, AlgebraicValue r) + { + return AlgebraicValue.Compare(type, l, r); + } + + public int GetHashCode(AlgebraicValue value) + { + var stream = new MemoryStream(); + var writer = new BinaryWriter(stream); + value.Serialize(type, writer); + var s = stream.ToArray(); + if (s.Length >= 4) + { + return BitConverter.ToInt32(s, 0); + } + return s.Sum(b => b); + } + } + } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 54db28147fa..b9dfd94205b 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -1,17 +1,17 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Collections.Concurrent; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Net.WebSockets; using System.Reflection; -using System.Text; +using System.Text; +using System.Threading; +using System.Threading.Tasks; using ClientApi; using Newtonsoft.Json; using SpacetimeDB.SATS; -using System.Threading; -using System.IO; -using System.Threading.Tasks; - + namespace SpacetimeDB { public class SpacetimeDBClient @@ -34,7 +34,7 @@ public class SubscriptionRequest public string subscriptionQuery; } - public struct DbEvent + public struct DbOp { public ClientCache.TableCache table; public TableOp op; @@ -42,6 +42,7 @@ public struct DbEvent public object oldValue; public byte[] deletedPk; public byte[] insertedPk; + public AlgebraicValue primaryKeyValue; } public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, SpacetimeDB.ReducerEventBase dbEvent); @@ -88,7 +89,7 @@ public struct DbEvent private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; - public static ClientCache clientDB; + public static ClientCache clientDB; public static Dictionary> reducerEventCache = new Dictionary>(); public static Dictionary> deserializeEventCache = new Dictionary>(); @@ -98,46 +99,44 @@ public struct DbEvent public static SpacetimeDBClient instance; public ISpacetimeDBLogger Logger => logger; - private ISpacetimeDBLogger logger; + private ISpacetimeDBLogger logger; public static void CreateInstance(ISpacetimeDBLogger loggerToUse) - { - if (instance == null) - { - new SpacetimeDBClient(loggerToUse); - } - else - { - loggerToUse.LogError($"Instance already created."); - } + { + if (instance == null) + { + new SpacetimeDBClient(loggerToUse); + } + else + { + loggerToUse.LogError($"Instance already created."); + } } - public Type FindReducerType() - { - // Get all loaded assemblies - Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - - // Iterate over each assembly and search for the type - foreach (Assembly assembly in assemblies) - { - // Get all types in the assembly - Type[] types = assembly.GetTypes(); - - // Search for the class with the attribute ReducerClass - foreach (Type type in types) - { - if (type.GetCustomAttribute() != null) - { - return type; - } - } - - } - - // If the type is not found in any assembly, return null or throw an exception - return null; - } + public Type FindReducerType() + { + // Get all loaded assemblies + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + // Iterate over each assembly and search for the type + foreach (Assembly assembly in assemblies) + { + // Get all types in the assembly + Type[] types = assembly.GetTypes(); + + // Search for the class with the attribute ReducerClass + foreach (Type type in types) + { + if (type.GetCustomAttribute() != null) + { + return type; + } + } + } + + // If the type is not found in any assembly, return null or throw an exception + return null; + } protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) { @@ -161,7 +160,7 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) webSocket.OnMessage += OnMessageReceived; webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); webSocket.OnConnect += () => onConnect?.Invoke(); - webSocket.OnConnectError += (a,b) => onConnectError?.Invoke(a,b); + webSocket.OnConnectError += (a, b) => onConnectError?.Invoke(a, b); webSocket.OnSendError += a => onSendError?.Invoke(a); clientDB = new ClientCache(); @@ -188,31 +187,30 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) } var reducerType = FindReducerType(); - if (reducerType != null) - { - // cache all our reducer events by their function name - foreach (var methodInfo in reducerType.GetMethods()) + if (reducerType != null) { - if (methodInfo.GetCustomAttribute() is - { } reducerEvent) + // cache all our reducer events by their function name + foreach (var methodInfo in reducerType.GetMethods()) { - reducerEventCache.Add(reducerEvent.FunctionName, (Func)methodInfo.CreateDelegate(typeof(Func))); - } + if (methodInfo.GetCustomAttribute() is + { } reducerEvent) + { + reducerEventCache.Add(reducerEvent.FunctionName, (Func)methodInfo.CreateDelegate(typeof(Func))); + } - if (methodInfo.GetCustomAttribute() is - { } deserializeEvent) - { - deserializeEventCache.Add(deserializeEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); + if (methodInfo.GetCustomAttribute() is + { } deserializeEvent) + { + deserializeEventCache.Add(deserializeEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); + } } - } } - else - { - loggerToUse.LogError($"Could not find reducer type. Have you run spacetime generate?"); + else + { + loggerToUse.LogError($"Could not find reducer type. Have you run spacetime generate?"); } _cancellationToken = _cancellationTokenSource.Token; - messageProcessThread = new Thread(ProcessMessages); messageProcessThread.Start(); } @@ -220,41 +218,45 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) struct ProcessedMessage { public Message message; - public IList events; + public IList dbOps; } private readonly BlockingCollection _messageQueue = new BlockingCollection(new ConcurrentQueue()); - private readonly BlockingCollection _nextMessageQueue = new BlockingCollection(new ConcurrentQueue()); - + private readonly BlockingCollection _nextMessageQueue = new BlockingCollection(new ConcurrentQueue()); + CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - CancellationToken _cancellationToken; + CancellationToken _cancellationToken; void ProcessMessages() { while (!isClosing) { - try - { + try + { var bytes = _messageQueue.Take(_cancellationToken); var (m, events) = PreProcessMessage(bytes); var processedMessage = new ProcessedMessage { message = m, - events = events, + dbOps = events, }; - _nextMessageQueue.Add(processedMessage); + _nextMessageQueue.Add(processedMessage); } - catch(OperationCanceledException) - { - // Normal shutdown - return; + catch (OperationCanceledException) + { + // Normal shutdown + return; } } - (Message, List) PreProcessMessage(byte[] bytes) + (Message, List) PreProcessMessage(byte[] bytes) { - var dbEvents = new List(); + var dbOps = new List(); + + // Used when convering matching Insert/Delete ops into Update + var insertOps = new List(); + var message = ClientApi.Message.Parser.ParseFrom(bytes); using var stream = new MemoryStream(); using var reader = new BinaryReader(stream); @@ -285,6 +287,9 @@ void ProcessMessages() continue; } + var primaryKeyType = table.GetPrimaryKeyType(table.RowSchema); + var deleteOps = new Dictionary(new AlgebraicValue.AlgebraicValueComparer(primaryKeyType)); + insertOps.Clear(); foreach (var row in update.TableRowOperations) { var rowPk = row.RowPk.ToByteArray(); @@ -293,86 +298,101 @@ void ProcessMessages() stream.Write(rowValue, 0, rowValue.Length); stream.Position = 0; stream.SetLength(rowValue.Length); + var decodedRow = AlgebraicValue.Deserialize(table.RowSchema, reader); + if (decodedRow == null) + { + throw new Exception("Failed to deserialize row"); + } - switch (row.Op) + DbOp dbOp; + AlgebraicValue primaryKeyValue = table.GetPrimaryKeyValue(decodedRow); + if (row.Op == TableRowOperation.Types.OperationType.Delete) { - case TableRowOperation.Types.OperationType.Delete: - dbEvents.Add(new DbEvent - { - table = table, - deletedPk = rowPk, - op = TableOp.Delete, - newValue = null, - // We cannot grab the old value here because there might be other - // pending operations that will execute before us. We should only - // set this value on the main thread where we know there are no other - // operations which could remove this value. - oldValue = null, - }); - break; - case TableRowOperation.Types.OperationType.Insert: - // If we already have this row, we can ignore it - if (table.entries.ContainsKey(rowPk)) - { - continue; - } + dbOp = new DbOp + { + table = table, + deletedPk = rowPk, + op = TableOp.Delete, + newValue = null, + // We cannot grab the old value here because there might be other + // pending operations that will execute before us. We should only + // set this value on the main thread where we know there are no other + // operations which could remove this value. + oldValue = null, + primaryKeyValue = primaryKeyValue + }; + } + else + { + // Skip this insert if we already have it + if (table.entries.ContainsKey(rowPk)) + { + continue; + } - var algebraicValue = AlgebraicValue.Deserialize(table.RowSchema, reader); - if(algebraicValue == null) - { - throw new Exception("Failed to deserialize row"); - } - table.SetDecodedValue(rowPk, algebraicValue, out var obj); - dbEvents.Add(new DbEvent + table.SetDecodedValue(rowPk, decodedRow, out var obj); + dbOp = new DbOp + { + table = table, + insertedPk = rowPk, + op = TableOp.Insert, + newValue = obj, + oldValue = null, + primaryKeyValue = primaryKeyValue + }; + } + + if (primaryKeyType != null) + { + if (row.Op == TableRowOperation.Types.OperationType.Delete) + { + deleteOps[primaryKeyValue] = dbOp; + } + else + { + insertOps.Add(dbOp); + } + } + else + { + dbOps.Add(dbOp); + } + } + + if (primaryKeyType != null) + { + // Replace Delete/Insert pairs with identical primary keys with an Update. + // + // !!TODO!!: Currently this code interprets Insert/Delete or Delete/Insert pairs as Updates. + // Note that if a user inserts and then deletes a row with the same primary key in a + // spacetimedb module, this is interpreted as an Update, while effectively it is a NoOp. + for (var i = 0; i < insertOps.Count; i++) + { + var insertOp = insertOps[i]; + if (deleteOps.TryGetValue(insertOp.primaryKeyValue, out var deleteOp)) + { + // We found an insert with a matching delete. + // Replace it with an update operation. + insertOps[i] = new DbOp { - table = table, - insertedPk = rowPk, - op = TableOp.Insert, - newValue = obj, - oldValue = null, - }); - break; + insertedPk = insertOp.insertedPk, + deletedPk = deleteOp.deletedPk, + table = insertOp.table, + op = TableOp.Update + }; + deleteOps.Remove(insertOp.primaryKeyValue); + } } + dbOps.AddRange(insertOps); + dbOps.AddRange(deleteOps.Values); } } - break; case ClientApi.Message.TypeOneofCase.IdentityToken: break; case ClientApi.Message.TypeOneofCase.Event: break; } - - // Factor out any insert/deletes into updates - for (var x = 0; x < dbEvents.Count; x++) - { - var insertEvent = dbEvents[x]; - if (insertEvent.op != TableOp.Insert) - { - continue; - } - - for (var y = 0; y < dbEvents.Count; y++) - { - var deleteEvent = dbEvents[y]; - if (deleteEvent.op != TableOp.Delete || deleteEvent.table != insertEvent.table - || !insertEvent.table.ComparePrimaryKey(insertEvent.insertedPk, deleteEvent.deletedPk)) - { - continue; - } - - var updateEvent = new DbEvent - { - deletedPk = deleteEvent.deletedPk, - insertedPk = insertEvent.insertedPk, - op = TableOp.Update, - table = insertEvent.table, - }; - dbEvents[x] = updateEvent; - dbEvents.RemoveAt(y); - break; - } - } if (message.TypeCase == Message.TypeOneofCase.SubscriptionUpdate) { @@ -393,26 +413,25 @@ void ProcessMessages() .Where(a => a.Op == TableRowOperation.Types.OperationType.Insert) .Select(b => b.RowPk.ToByteArray()); var existingPks = clientTable.entries.Select(a => a.Key); - dbEvents.AddRange(existingPks.Except(newPks, new ClientCache.TableCache.ByteArrayComparer()) - .Select(a => new DbEvent - { - deletedPk = a, - newValue = null, - oldValue = clientTable.entries[a].Item2, - op = TableOp.Delete, - table = clientTable, - })); + dbOps.AddRange(existingPks.Except(newPks, new ClientCache.TableCache.ByteArrayComparer()) + .Select(a => new DbOp + { + deletedPk = a, + newValue = null, + oldValue = clientTable.entries[a].Item2, + op = TableOp.Delete, + table = clientTable, + })); } } - - if (message.TypeCase == Message.TypeOneofCase.TransactionUpdate && + if (message.TypeCase == Message.TypeOneofCase.TransactionUpdate && deserializeEventCache.TryGetValue(message.TransactionUpdate.Event.FunctionCall.Reducer, out var deserializer)) { deserializer.Invoke(message.TransactionUpdate.Event); } - return (message, dbEvents); + return (message, dbOps); } } @@ -421,7 +440,7 @@ public void Close() isClosing = true; connectionClosed = true; webSocket.Close(); - _cancellationTokenSource.Cancel(); + _cancellationTokenSource.Cancel(); webSocket = null; } @@ -432,9 +451,9 @@ public void Close() /// The name or address of the database to connect to /// Should websocket use SSL public void Connect(string token, string host, string addressOrName, bool sslEnabled = true) - { - isClosing = false; - + { + isClosing = false; + logger.Log($"SpacetimeDBClient: Connecting to {host} {addressOrName}"); Task.Run(async () => { @@ -455,22 +474,22 @@ public void Connect(string token, string host, string addressOrName, bool sslEna }); } - private void OnMessageProcessComplete(Message message, IList events) + private void OnMessageProcessComplete(Message message, IList dbOps) { switch (message.TypeCase) { case Message.TypeOneofCase.SubscriptionUpdate: case Message.TypeOneofCase.TransactionUpdate: // First trigger OnBeforeDelete - for (var i = 0; i < events.Count; i++) + for (var i = 0; i < dbOps.Count; i++) { // TODO: Reimplement updates when we add support for primary keys - var ev = events[i]; - if (ev.op == TableOp.Delete && ev.table.TryGetValue(ev.deletedPk, out var oldVal)) + var update = dbOps[i]; + if (update.op == TableOp.Delete && update.table.TryGetValue(update.deletedPk, out var oldVal)) { try { - ev.table.BeforeDeleteCallback?.Invoke(oldVal, message.TransactionUpdate?.Event); + update.table.BeforeDeleteCallback?.Invoke(oldVal, message.TransactionUpdate?.Event); } catch (Exception e) { @@ -480,48 +499,48 @@ private void OnMessageProcessComplete(Message message, IList events) } // Apply all of the state - for (var i = 0; i < events.Count; i++) + for (var i = 0; i < dbOps.Count; i++) { // TODO: Reimplement updates when we add support for primary keys - var ev = events[i]; - switch (ev.op) + var update = dbOps[i]; + switch (update.op) { case TableOp.Delete: - ev.oldValue = events[i].table.DeleteEntry(ev.deletedPk); - if (ev.oldValue != null) + update.oldValue = dbOps[i].table.DeleteEntry(update.deletedPk); + if (update.oldValue != null) { - ev.table.InternalValueDeletedCallback(ev.oldValue); + update.table.InternalValueDeletedCallback(update.oldValue); } - events[i] = ev; + dbOps[i] = update; break; case TableOp.Insert: - ev.newValue = events[i].table.InsertEntry(ev.insertedPk); - ev.table.InternalValueInsertedCallback(ev.newValue); - events[i] = ev; + update.newValue = dbOps[i].table.InsertEntry(update.insertedPk); + update.table.InternalValueInsertedCallback(update.newValue); + dbOps[i] = update; break; case TableOp.Update: - ev.oldValue = events[i].table.DeleteEntry(ev.deletedPk); - ev.newValue = events[i].table.InsertEntry(ev.insertedPk); - if (ev.oldValue != null) + update.oldValue = dbOps[i].table.DeleteEntry(update.deletedPk); + update.newValue = dbOps[i].table.InsertEntry(update.insertedPk); + if (update.oldValue != null) { - ev.table.InternalValueDeletedCallback(ev.oldValue); + update.table.InternalValueDeletedCallback(update.oldValue); } - ev.table.InternalValueInsertedCallback(ev.newValue); - events[i] = ev; + update.table.InternalValueInsertedCallback(update.newValue); + dbOps[i] = update; break; default: throw new ArgumentOutOfRangeException(); } } - + // Send out events - var eventCount = events.Count; - for (var i = 0; i < eventCount; i++) + var updateCount = dbOps.Count; + for (var i = 0; i < updateCount; i++) { - var tableName = events[i].table.ClientTableType.Name; - var tableOp = events[i].op; - var oldValue = events[i].oldValue; - var newValue = events[i].newValue; + var tableName = dbOps[i].table.ClientTableType.Name; + var tableOp = dbOps[i].op; + var oldValue = dbOps[i].oldValue; + var newValue = dbOps[i].newValue; switch (tableOp) { @@ -530,21 +549,21 @@ private void OnMessageProcessComplete(Message message, IList events) { try { - if (events[i].table.InsertCallback != null) + if (dbOps[i].table.InsertCallback != null) { - events[i].table.InsertCallback.Invoke(newValue, message.TransactionUpdate?.Event); + dbOps[i].table.InsertCallback.Invoke(newValue, message.TransactionUpdate?.Event); } } catch (Exception e) { logger.LogException(e); } - + try { - if (events[i].table.RowUpdatedCallback != null) + if (dbOps[i].table.RowUpdatedCallback != null) { - events[i].table.RowUpdatedCallback + dbOps[i].table.RowUpdatedCallback .Invoke(tableOp, null, newValue, message.TransactionUpdate?.Event); } } @@ -564,11 +583,11 @@ private void OnMessageProcessComplete(Message message, IList events) { if (oldValue != null && newValue == null) { - if (events[i].table.DeleteCallback != null) + if (dbOps[i].table.DeleteCallback != null) { try { - events[i].table.DeleteCallback.Invoke(oldValue, message.TransactionUpdate?.Event); + dbOps[i].table.DeleteCallback.Invoke(oldValue, message.TransactionUpdate?.Event); } catch (Exception e) { @@ -576,12 +595,12 @@ private void OnMessageProcessComplete(Message message, IList events) } } - if (events[i].table.RowUpdatedCallback != null) + if (dbOps[i].table.RowUpdatedCallback != null) { try { - events[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); + dbOps[i].table.RowUpdatedCallback + .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); } catch (Exception e) { @@ -602,22 +621,22 @@ private void OnMessageProcessComplete(Message message, IList events) { try { - if (events[i].table.UpdateCallback != null) + if (dbOps[i].table.UpdateCallback != null) { - events[i].table.UpdateCallback.Invoke(oldValue, newValue, message.TransactionUpdate?.Event); + dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, message.TransactionUpdate?.Event); } } catch (Exception e) { logger.LogException(e); } - + try { - if (events[i].table.RowUpdatedCallback != null) + if (dbOps[i].table.RowUpdatedCallback != null) { - events[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); + dbOps[i].table.RowUpdatedCallback + .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); } } catch (Exception e) @@ -680,20 +699,20 @@ private void OnMessageProcessComplete(Message message, IList events) public void InternalCallReducer(string json) { - if(!webSocket.IsConnected) - { - logger.LogError("Cannot call reducer, not connected to server!"); - return; + if (!webSocket.IsConnected) + { + logger.LogError("Cannot call reducer, not connected to server!"); + return; } webSocket.Send(Encoding.ASCII.GetBytes("{ \"call\": " + json + " }")); } public void Subscribe(List queries) { - if(!webSocket.IsConnected) - { - logger.LogError("Cannot subscribe, not connected to server!"); - return; + if (!webSocket.IsConnected) + { + logger.LogError("Cannot subscribe, not connected to server!"); + return; } var json = JsonConvert.SerializeObject(queries); webSocket.Send(Encoding.ASCII.GetBytes("{ \"subscribe\": { \"query_strings\": " + json + " }}")); @@ -705,7 +724,7 @@ public void Update() while (_nextMessageQueue.TryTake(out var nextMessage)) { - OnMessageProcessComplete(nextMessage.message, nextMessage.events); + OnMessageProcessComplete(nextMessage.message, nextMessage.dbOps); } } } From e0524fa4eb07dbde7859857fa0274e6bbadf059a Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Wed, 2 Aug 2023 10:15:37 -0400 Subject: [PATCH 052/223] Update version to 0.6.0 (#48) * Update version to 0.6.0 * Change PackageId to match other packages --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/SpacetimeDBCSharpSDK.csproj | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sdks/csharp/SpacetimeDBCSharpSDK.csproj b/sdks/csharp/SpacetimeDBCSharpSDK.csproj index e3112f7946f..181ac417016 100644 --- a/sdks/csharp/SpacetimeDBCSharpSDK.csproj +++ b/sdks/csharp/SpacetimeDBCSharpSDK.csproj @@ -5,7 +5,7 @@ enable enable True - spacetimedbsdk + SpacetimeDB.ClientSDK SpacetimeDB SDK derek_clockwork Clockwork Labs @@ -16,17 +16,14 @@ logo.png README.md https://github.com/clockworklabs/SpacetimeDBCSharpSDK - 0.5.0 - 0.5.0 + 0.6.0 + 0.6.0 - - - From 1003db20f81ff36b217262e0d36e8a4b76b58e31 Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Tue, 8 Aug 2023 13:50:00 -0400 Subject: [PATCH 053/223] Commit quickstart example (#44) * Commit quickstart example * GetHashCode fix for Identity.cs * Remove SDK from quickstart project and add nuget package. Rename spacetime_types folder to module_bindings --------- Co-authored-by: Derek Brinkmann --- .../examples/quickstart/client/Program.cs | 196 +++++++++++ .../examples/quickstart/client/client.csproj | 20 ++ .../examples/quickstart/client/client.sln | 25 ++ .../client/module_bindings/Message.cs | 144 ++++++++ .../client/module_bindings/Reducer.cs | 7 + .../client/module_bindings/ReducerEvent.cs | 67 ++++ .../module_bindings/SendMessageReducer.cs | 66 ++++ .../client/module_bindings/SetNameReducer.cs | 66 ++++ .../quickstart/client/module_bindings/User.cs | 138 ++++++++ .../quickstart/server/.cargo/config.toml | 2 + .../examples/quickstart/server/.gitignore | 13 + .../examples/quickstart/server/Cargo.lock | 313 ++++++++++++++++++ .../examples/quickstart/server/Cargo.toml | 14 + .../examples/quickstart/server/src/lib.rs | 91 +++++ sdks/csharp/src/Identity.cs | 6 +- 15 files changed, 1165 insertions(+), 3 deletions(-) create mode 100644 sdks/csharp/examples/quickstart/client/Program.cs create mode 100644 sdks/csharp/examples/quickstart/client/client.csproj create mode 100644 sdks/csharp/examples/quickstart/client/client.sln create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/Message.cs create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/Reducer.cs create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/User.cs create mode 100644 sdks/csharp/examples/quickstart/server/.cargo/config.toml create mode 100644 sdks/csharp/examples/quickstart/server/.gitignore create mode 100644 sdks/csharp/examples/quickstart/server/Cargo.lock create mode 100644 sdks/csharp/examples/quickstart/server/Cargo.toml create mode 100644 sdks/csharp/examples/quickstart/server/src/lib.rs diff --git a/sdks/csharp/examples/quickstart/client/Program.cs b/sdks/csharp/examples/quickstart/client/Program.cs new file mode 100644 index 00000000000..bf564ab9ae1 --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/Program.cs @@ -0,0 +1,196 @@ +using SpacetimeDB; +using SpacetimeDB.Types; +using System.Collections.Concurrent; + +// our local client SpacetimeDB identity +Identity? local_identity = null; +// declare a thread safe queue to store commands in format (command, args) +ConcurrentQueue<(string, string)> input_queue = new ConcurrentQueue<(string, string)>(); +// declare a threadsafe cancel token to cancel the process loop +CancellationTokenSource cancel_token = new CancellationTokenSource(); + +void Main() +{ + AuthToken.Init(".spacetime_csharp_quickstart"); + + // create the client, pass in a logger to see debug messages + SpacetimeDBClient.CreateInstance(new ConsoleLogger()); + + RegisterCallbacks(); + + // spawn a thread to call process updates and process commands + var thread = new Thread(ProcessThread); + thread.Start(); + + InputLoop(); + + cancel_token.Cancel(); + thread.Join(); +} + +void RegisterCallbacks() +{ + SpacetimeDBClient.instance.onConnect += OnConnect; + SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; + SpacetimeDBClient.instance.onSubscriptionApplied += OnSubscriptionApplied; + + User.OnInsert += User_OnInsert; + User.OnUpdate += User_OnUpdate; + + Message.OnInsert += Message_OnInsert; + + Reducer.OnSetNameEvent += Reducer_OnSetNameEvent; + Reducer.OnSendMessageEvent += Reducer_OnSendMessageEvent; +} + +string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()!.Substring(0, 8); + +void User_OnInsert(User insertedValue, ReducerEvent dbEvent) +{ + if (insertedValue.Online) + { + Console.WriteLine($"{UserNameOrIdentity(insertedValue)} is online"); + } +} + +void User_OnUpdate(User oldValue, User newValue, ReducerEvent dbEvent) +{ + if (oldValue.Name != newValue.Name) + { + Console.WriteLine($"{UserNameOrIdentity(oldValue)} renamed to {newValue.Name}"); + } + if (oldValue.Online != newValue.Online) + { + if (newValue.Online) + { + Console.WriteLine($"{UserNameOrIdentity(newValue)} connected."); + } + else + { + Console.WriteLine($"{UserNameOrIdentity(newValue)} disconnected."); + } + } +} + +void PrintMessage(Message message) +{ + var sender = User.FilterByIdentity(message.Sender); + var senderName = "unknown"; + if (sender != null) + { + senderName = UserNameOrIdentity(sender); + } + + Console.WriteLine($"{senderName}: {message.Text}"); +} + +void Message_OnInsert(Message insertedValue, ReducerEvent dbEvent) +{ + if (dbEvent != null) + { + PrintMessage(insertedValue); + } +} + +void Reducer_OnSetNameEvent(ReducerEvent reducerEvent, string name) +{ + if (reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) + { + Console.Write($"Failed to change name to {name}"); + } +} + +void Reducer_OnSendMessageEvent(ReducerEvent reducerEvent, string text) +{ + if (reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) + { + Console.Write($"Failed to send message {text}"); + } +} + +void OnConnect() +{ + SpacetimeDBClient.instance.Subscribe(new List { "SELECT * FROM User", "SELECT * FROM Message" }); +} + +void OnIdentityReceived(string authToken, Identity identity) +{ + local_identity = identity; + AuthToken.SaveToken(authToken); +} + +void PrintMessagesInOrder() +{ + foreach (Message message in Message.Iter().OrderBy(item => item.Sent)) + { + PrintMessage(message); + } +} + +void OnSubscriptionApplied() +{ + Console.WriteLine("Connected"); + PrintMessagesInOrder(); +} + +const string HOST = "localhost:3000"; +const string DBNAME = "chat2"; +const bool SSL_ENABLED = false; + +void ProcessThread() +{ + SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME, SSL_ENABLED); + + // loop until cancellation token + while (!cancel_token.IsCancellationRequested) + { + SpacetimeDBClient.instance.Update(); + + ProcessCommands(); + + Thread.Sleep(100); + } + + SpacetimeDBClient.instance.Close(); +} + +void InputLoop() +{ + while (true) + { + var input = Console.ReadLine(); + if(input == null) + { + break; + } + + if(input.StartsWith("/name ")) + { + input_queue.Enqueue(("name", input.Substring(6))); + continue; + } + else + { + input_queue.Enqueue(("message", input)); + } + } +} + +void ProcessCommands() +{ + // process input queue commands + while (input_queue.TryDequeue(out var command)) + { + switch (command.Item1) + { + case "message": + Reducer.SendMessage(command.Item2); + break; + case "name": + Reducer.SetName(command.Item2); + break; + } + } +} + +Main(); \ No newline at end of file diff --git a/sdks/csharp/examples/quickstart/client/client.csproj b/sdks/csharp/examples/quickstart/client/client.csproj new file mode 100644 index 00000000000..b5bf94d5eda --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/client.csproj @@ -0,0 +1,20 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + + + + + + diff --git a/sdks/csharp/examples/quickstart/client/client.sln b/sdks/csharp/examples/quickstart/client/client.sln new file mode 100644 index 00000000000..f77ec29b6c8 --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/client.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33717.318 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "client.csproj", "{8F33709C-DEE9-41CC-A477-D6128E3700B1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {35C59D87-64E5-4A6C-B1D5-2241B946E847} + EndGlobalSection +EndGlobal diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs new file mode 100644 index 00000000000..223f57b4c39 --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs @@ -0,0 +1,144 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +using System; +using System.Collections.Generic; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + public partial class Message : IDatabaseTable + { + [Newtonsoft.Json.JsonProperty("sender")] + public SpacetimeDB.Identity Sender; + [Newtonsoft.Json.JsonProperty("sent")] + public ulong Sent; + [Newtonsoft.Json.JsonProperty("text")] + public string Text; + + + private static void InternalOnValueInserted(object insertedValue) + { + var val = (Message)insertedValue; + } + + private static void InternalOnValueDeleted(object deletedValue) + { + var val = (Message)deletedValue; + } + + public static SpacetimeDB.SATS.AlgebraicType GetAlgebraicType() + { + return SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] + { + new SpacetimeDB.SATS.ProductTypeElement("sender", SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] + { + new SpacetimeDB.SATS.ProductTypeElement("__identity_bytes", SpacetimeDB.SATS.AlgebraicType.CreateArrayType(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.U8))), + })), + new SpacetimeDB.SATS.ProductTypeElement("sent", SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.U64)), + new SpacetimeDB.SATS.ProductTypeElement("text", SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String)), + }); + } + + public static explicit operator Message(SpacetimeDB.SATS.AlgebraicValue value) + { + if (value == null) { + return null; + } + var productValue = value.AsProductValue(); + return new Message + { + Sender = SpacetimeDB.Identity.From(productValue.elements[0].AsProductValue().elements[0].AsBytes()), + Sent = productValue.elements[1].AsU64(), + Text = productValue.elements[2].AsString(), + }; + } + + public static System.Collections.Generic.IEnumerable Iter() + { + foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("Message")) + { + yield return (Message)entry.Item2; + } + } + public static int Count() + { + return SpacetimeDBClient.clientDB.Count("Message"); + } + public static System.Collections.Generic.IEnumerable FilterBySender(SpacetimeDB.Identity value) + { + foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("Message")) + { + var productValue = entry.Item1.AsProductValue(); + var compareValue = Identity.From(productValue.elements[0].AsProductValue().elements[0].AsBytes()); + if (compareValue == value) { + yield return (Message)entry.Item2; + } + } + } + + public static System.Collections.Generic.IEnumerable FilterBySent(ulong value) + { + foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("Message")) + { + var productValue = entry.Item1.AsProductValue(); + var compareValue = (ulong)productValue.elements[1].AsU64(); + if (compareValue == value) { + yield return (Message)entry.Item2; + } + } + } + + public static System.Collections.Generic.IEnumerable FilterByText(string value) + { + foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("Message")) + { + var productValue = entry.Item1.AsProductValue(); + var compareValue = (string)productValue.elements[2].AsString(); + if (compareValue == value) { + yield return (Message)entry.Item2; + } + } + } + + public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, SpacetimeDB.SATS.AlgebraicValue _v1, SpacetimeDB.SATS.AlgebraicValue _v2) + { + return false; + } + + public delegate void InsertEventHandler(Message insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); + public delegate void UpdateEventHandler(Message oldValue, Message newValue, SpacetimeDB.Types.ReducerEvent dbEvent); + public delegate void DeleteEventHandler(Message deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); + public delegate void RowUpdateEventHandler(SpacetimeDBClient.TableOp op, Message oldValue, Message newValue, SpacetimeDB.Types.ReducerEvent dbEvent); + public static event InsertEventHandler OnInsert; + public static event UpdateEventHandler OnUpdate; + public static event DeleteEventHandler OnBeforeDelete; + public static event DeleteEventHandler OnDelete; + public static event RowUpdateEventHandler OnRowUpdate; + + public static void OnInsertEvent(object newValue, ClientApi.Event dbEvent) + { + OnInsert?.Invoke((Message)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + + public static void OnUpdateEvent(object oldValue, object newValue, ClientApi.Event dbEvent) + { + OnUpdate?.Invoke((Message)oldValue,(Message)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + + public static void OnBeforeDeleteEvent(object oldValue, ClientApi.Event dbEvent) + { + OnBeforeDelete?.Invoke((Message)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + + public static void OnDeleteEvent(object oldValue, ClientApi.Event dbEvent) + { + OnDelete?.Invoke((Message)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + + public static void OnRowUpdateEvent(SpacetimeDBClient.TableOp op, object oldValue, object newValue, ClientApi.Event dbEvent) + { + OnRowUpdate?.Invoke(op, (Message)oldValue,(Message)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + } +} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Reducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/Reducer.cs new file mode 100644 index 00000000000..f25e5e07b71 --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/Reducer.cs @@ -0,0 +1,7 @@ +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + [ReducerClass] + public partial class Reducer { } +} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs new file mode 100644 index 00000000000..344e6e383ef --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs @@ -0,0 +1,67 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +using System; +using ClientApi; +using Newtonsoft.Json.Linq; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + public enum ReducerType + { + None, + SendMessage, + SetName, + } + + public partial class ReducerEvent : ReducerEventBase + { + public ReducerType Reducer { get; private set; } + + public ReducerEvent(ReducerType reducer, string reducerName, ulong timestamp, SpacetimeDB.Identity identity, string errMessage, ClientApi.Event.Types.Status status, object args) + : base(reducerName, timestamp, identity, errMessage, status, args) + { + Reducer = reducer; + } + + public SendMessageArgsStruct SendMessageArgs + { + get + { + if (Reducer != ReducerType.SendMessage) throw new SpacetimeDB.ReducerMismatchException(Reducer.ToString(), "SendMessage"); + return (SendMessageArgsStruct)Args; + } + } + public SetNameArgsStruct SetNameArgs + { + get + { + if (Reducer != ReducerType.SetName) throw new SpacetimeDB.ReducerMismatchException(Reducer.ToString(), "SetName"); + return (SetNameArgsStruct)Args; + } + } + + public object[] GetArgsAsObjectArray() + { + switch (Reducer) + { + case ReducerType.SendMessage: + { + var args = SendMessageArgs; + return new object[] { + args.Text, + }; + } + case ReducerType.SetName: + { + var args = SetNameArgs; + return new object[] { + args.Name, + }; + } + default: throw new System.Exception($"Unhandled reducer case: {Reducer}. Please run SpacetimeDB code generator"); + } + } + } +} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs new file mode 100644 index 00000000000..9b37c0f9f70 --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs @@ -0,0 +1,66 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +using System; +using ClientApi; +using Newtonsoft.Json.Linq; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + public static partial class Reducer + { + public delegate void SendMessageHandler(ReducerEvent reducerEvent, string text); + public static event SendMessageHandler OnSendMessageEvent; + + public static void SendMessage(string text) + { + var _argArray = new object[] {text}; + var _message = new SpacetimeDBClient.ReducerCallRequest { + fn = "send_message", + args = _argArray, + }; + Newtonsoft.Json.JsonSerializerSettings _settings = new Newtonsoft.Json.JsonSerializerSettings + { + Converters = { new SpacetimeDB.SomeWrapperConverter(), new SpacetimeDB.EnumWrapperConverter() }, + ContractResolver = new SpacetimeDB.JsonContractResolver(), + }; + SpacetimeDBClient.instance.InternalCallReducer(Newtonsoft.Json.JsonConvert.SerializeObject(_message, _settings)); + } + + [ReducerCallback(FunctionName = "send_message")] + public static bool OnSendMessage(ClientApi.Event dbEvent) + { + if(OnSendMessageEvent != null) + { + var args = ((ReducerEvent)dbEvent.FunctionCall.CallInfo).SendMessageArgs; + OnSendMessageEvent((ReducerEvent)dbEvent.FunctionCall.CallInfo + ,(string)args.Text + ); + return true; + } + return false; + } + + [DeserializeEvent(FunctionName = "send_message")] + public static void SendMessageDeserializeEventArgs(ClientApi.Event dbEvent) + { + var args = new SendMessageArgsStruct(); + var bsatnBytes = dbEvent.FunctionCall.ArgBytes; + using var ms = new System.IO.MemoryStream(); + ms.SetLength(bsatnBytes.Length); + bsatnBytes.CopyTo(ms.GetBuffer(), 0); + ms.Position = 0; + using var reader = new System.IO.BinaryReader(ms); + var args_0_value = SpacetimeDB.SATS.AlgebraicValue.Deserialize(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String), reader); + args.Text = args_0_value.AsString(); + dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.SendMessage, "send_message", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), dbEvent.Message, dbEvent.Status, args); + } + } + + public partial class SendMessageArgsStruct + { + public string Text; + } + +} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs new file mode 100644 index 00000000000..c4806057d4d --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs @@ -0,0 +1,66 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +using System; +using ClientApi; +using Newtonsoft.Json.Linq; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + public static partial class Reducer + { + public delegate void SetNameHandler(ReducerEvent reducerEvent, string name); + public static event SetNameHandler OnSetNameEvent; + + public static void SetName(string name) + { + var _argArray = new object[] {name}; + var _message = new SpacetimeDBClient.ReducerCallRequest { + fn = "set_name", + args = _argArray, + }; + Newtonsoft.Json.JsonSerializerSettings _settings = new Newtonsoft.Json.JsonSerializerSettings + { + Converters = { new SpacetimeDB.SomeWrapperConverter(), new SpacetimeDB.EnumWrapperConverter() }, + ContractResolver = new SpacetimeDB.JsonContractResolver(), + }; + SpacetimeDBClient.instance.InternalCallReducer(Newtonsoft.Json.JsonConvert.SerializeObject(_message, _settings)); + } + + [ReducerCallback(FunctionName = "set_name")] + public static bool OnSetName(ClientApi.Event dbEvent) + { + if(OnSetNameEvent != null) + { + var args = ((ReducerEvent)dbEvent.FunctionCall.CallInfo).SetNameArgs; + OnSetNameEvent((ReducerEvent)dbEvent.FunctionCall.CallInfo + ,(string)args.Name + ); + return true; + } + return false; + } + + [DeserializeEvent(FunctionName = "set_name")] + public static void SetNameDeserializeEventArgs(ClientApi.Event dbEvent) + { + var args = new SetNameArgsStruct(); + var bsatnBytes = dbEvent.FunctionCall.ArgBytes; + using var ms = new System.IO.MemoryStream(); + ms.SetLength(bsatnBytes.Length); + bsatnBytes.CopyTo(ms.GetBuffer(), 0); + ms.Position = 0; + using var reader = new System.IO.BinaryReader(ms); + var args_0_value = SpacetimeDB.SATS.AlgebraicValue.Deserialize(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String), reader); + args.Name = args_0_value.AsString(); + dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.SetName, "set_name", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), dbEvent.Message, dbEvent.Status, args); + } + } + + public partial class SetNameArgsStruct + { + public string Name; + } + +} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs new file mode 100644 index 00000000000..b50a45027c9 --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs @@ -0,0 +1,138 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +using System; +using System.Collections.Generic; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + public partial class User : IDatabaseTable + { + [Newtonsoft.Json.JsonProperty("identity")] + public SpacetimeDB.Identity Identity; + [Newtonsoft.Json.JsonProperty("name")] + [SpacetimeDB.Some] + public string Name; + [Newtonsoft.Json.JsonProperty("online")] + public bool Online; + + private static Dictionary Identity_Index = new Dictionary(16); + + private static void InternalOnValueInserted(object insertedValue) + { + var val = (User)insertedValue; + Identity_Index[val.Identity] = val; + } + + private static void InternalOnValueDeleted(object deletedValue) + { + var val = (User)deletedValue; + Identity_Index.Remove(val.Identity); + } + + public static SpacetimeDB.SATS.AlgebraicType GetAlgebraicType() + { + return SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] + { + new SpacetimeDB.SATS.ProductTypeElement("identity", SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] + { + new SpacetimeDB.SATS.ProductTypeElement("__identity_bytes", SpacetimeDB.SATS.AlgebraicType.CreateArrayType(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.U8))), + })), + new SpacetimeDB.SATS.ProductTypeElement("name", SpacetimeDB.SATS.AlgebraicType.CreateSumType(new System.Collections.Generic.List + { + new SpacetimeDB.SATS.SumTypeVariant("some", SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String)), + new SpacetimeDB.SATS.SumTypeVariant("none", SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] + { + })), + })), + new SpacetimeDB.SATS.ProductTypeElement("online", SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.Bool)), + }); + } + + public static explicit operator User(SpacetimeDB.SATS.AlgebraicValue value) + { + if (value == null) { + return null; + } + var productValue = value.AsProductValue(); + return new User + { + Identity = SpacetimeDB.Identity.From(productValue.elements[0].AsProductValue().elements[0].AsBytes()), + Name = productValue.elements[1].AsSumValue().tag == 1 ? null : productValue.elements[1].AsSumValue().value.AsString(), + Online = productValue.elements[2].AsBool(), + }; + } + + public static System.Collections.Generic.IEnumerable Iter() + { + foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("User")) + { + yield return (User)entry.Item2; + } + } + public static int Count() + { + return SpacetimeDBClient.clientDB.Count("User"); + } + public static User FilterByIdentity(SpacetimeDB.Identity value) + { + Identity_Index.TryGetValue(value, out var r); + return r; + } + + public static System.Collections.Generic.IEnumerable FilterByOnline(bool value) + { + foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("User")) + { + var productValue = entry.Item1.AsProductValue(); + var compareValue = (bool)productValue.elements[2].AsBool(); + if (compareValue == value) { + yield return (User)entry.Item2; + } + } + } + + public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, SpacetimeDB.SATS.AlgebraicValue v1, SpacetimeDB.SATS.AlgebraicValue v2) + { + var primaryColumnValue1 = v1.AsProductValue().elements[0]; + var primaryColumnValue2 = v2.AsProductValue().elements[0]; + return SpacetimeDB.SATS.AlgebraicValue.Compare(t.product.elements[0].algebraicType, primaryColumnValue1, primaryColumnValue2); + } + + public delegate void InsertEventHandler(User insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); + public delegate void UpdateEventHandler(User oldValue, User newValue, SpacetimeDB.Types.ReducerEvent dbEvent); + public delegate void DeleteEventHandler(User deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); + public delegate void RowUpdateEventHandler(SpacetimeDBClient.TableOp op, User oldValue, User newValue, SpacetimeDB.Types.ReducerEvent dbEvent); + public static event InsertEventHandler OnInsert; + public static event UpdateEventHandler OnUpdate; + public static event DeleteEventHandler OnBeforeDelete; + public static event DeleteEventHandler OnDelete; + public static event RowUpdateEventHandler OnRowUpdate; + + public static void OnInsertEvent(object newValue, ClientApi.Event dbEvent) + { + OnInsert?.Invoke((User)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + + public static void OnUpdateEvent(object oldValue, object newValue, ClientApi.Event dbEvent) + { + OnUpdate?.Invoke((User)oldValue,(User)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + + public static void OnBeforeDeleteEvent(object oldValue, ClientApi.Event dbEvent) + { + OnBeforeDelete?.Invoke((User)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + + public static void OnDeleteEvent(object oldValue, ClientApi.Event dbEvent) + { + OnDelete?.Invoke((User)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + + public static void OnRowUpdateEvent(SpacetimeDBClient.TableOp op, object oldValue, object newValue, ClientApi.Event dbEvent) + { + OnRowUpdate?.Invoke(op, (User)oldValue,(User)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); + } + } +} diff --git a/sdks/csharp/examples/quickstart/server/.cargo/config.toml b/sdks/csharp/examples/quickstart/server/.cargo/config.toml new file mode 100644 index 00000000000..f4e8c002fc2 --- /dev/null +++ b/sdks/csharp/examples/quickstart/server/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-unknown-unknown" diff --git a/sdks/csharp/examples/quickstart/server/.gitignore b/sdks/csharp/examples/quickstart/server/.gitignore new file mode 100644 index 00000000000..91ad25847ba --- /dev/null +++ b/sdks/csharp/examples/quickstart/server/.gitignore @@ -0,0 +1,13 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# Spacetime ignore +/.spacetime diff --git a/sdks/csharp/examples/quickstart/server/Cargo.lock b/sdks/csharp/examples/quickstart/server/Cargo.lock new file mode 100644 index 00000000000..9174e943226 --- /dev/null +++ b/sdks/csharp/examples/quickstart/server/Cargo.lock @@ -0,0 +1,313 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + +[[package]] +name = "approx" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "decorum" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "281759d3c8a14f5c3f0c49363be56810fcd7f910422f97f2db850c2920fde5cf" +dependencies = [ + "approx", + "num-traits", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "proc-macro2" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "spacetime-module" +version = "0.1.0" +dependencies = [ + "anyhow", + "log", + "spacetimedb", +] + +[[package]] +name = "spacetimedb" +version = "0.5.0" +dependencies = [ + "log", + "once_cell", + "scoped-tls", + "spacetimedb-bindings-macro", + "spacetimedb-bindings-sys", + "spacetimedb-lib", +] + +[[package]] +name = "spacetimedb-bindings-macro" +version = "0.5.0" +dependencies = [ + "humantime", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "spacetimedb-bindings-sys" +version = "0.5.0" + +[[package]] +name = "spacetimedb-lib" +version = "0.5.0" +dependencies = [ + "anyhow", + "enum-as-inner", + "hex", + "itertools", + "sha3", + "spacetimedb-bindings-macro", + "spacetimedb-sats", + "thiserror", +] + +[[package]] +name = "spacetimedb-sats" +version = "0.5.0" +dependencies = [ + "arrayvec", + "decorum", + "enum-as-inner", + "itertools", + "spacetimedb-bindings-macro", + "thiserror", +] + +[[package]] +name = "syn" +version = "2.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/sdks/csharp/examples/quickstart/server/Cargo.toml b/sdks/csharp/examples/quickstart/server/Cargo.toml new file mode 100644 index 00000000000..d799f635699 --- /dev/null +++ b/sdks/csharp/examples/quickstart/server/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "spacetime-module" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib"] + +[dependencies] +spacetimedb = { path = "../../../../spacetimedb/crates/bindings" } +log = "0.4" +anyhow = "1.0" diff --git a/sdks/csharp/examples/quickstart/server/src/lib.rs b/sdks/csharp/examples/quickstart/server/src/lib.rs new file mode 100644 index 00000000000..3083a346cc3 --- /dev/null +++ b/sdks/csharp/examples/quickstart/server/src/lib.rs @@ -0,0 +1,91 @@ +use spacetimedb::{spacetimedb, ReducerContext, Identity, Timestamp}; +use anyhow::{Result, anyhow}; + +#[spacetimedb(table)] +pub struct User { + #[primarykey] + identity: Identity, + name: Option, + online: bool, +} + +#[spacetimedb(table)] +pub struct Message { + sender: Identity, + sent: Timestamp, + text: String, +} + +#[spacetimedb(init)] +pub fn init() { + // Called when the module is initially published +} + +#[spacetimedb(connect)] +pub fn identity_connected(ctx: ReducerContext) { + if let Some(user) = User::filter_by_identity(&ctx.sender) { + // If this is a returning user, i.e. we already have a `User` with this `Identity`, + // set `online: true`, but leave `name` and `identity` unchanged. + User::update_by_identity(&ctx.sender, User { online: true, ..user }); + } else { + // If this is a new user, create a `User` row for the `Identity`, + // which is online, but hasn't set a name. + User::insert(User { + name: None, + identity: ctx.sender, + online: true, + }).unwrap(); + } +} + +#[spacetimedb(disconnect)] +pub fn identity_disconnected(ctx: ReducerContext) { + if let Some(user) = User::filter_by_identity(&ctx.sender) { + User::update_by_identity(&ctx.sender, User { online: false, ..user }); + } else { + // This branch should be unreachable, + // as it doesn't make sense for a client to disconnect without connecting first. + log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender); + } +} + +fn validate_name(name: String) -> Result { + if name.is_empty() { + Err(anyhow!("Names must not be empty")) + } else { + Ok(name) + } +} + +#[spacetimedb(reducer)] +pub fn set_name(ctx: ReducerContext, name: String) -> Result<()> { + let name = validate_name(name)?; + if let Some(user) = User::filter_by_identity(&ctx.sender) { + User::update_by_identity(&ctx.sender, User { name: Some(name), ..user }); + Ok(()) + } else { + Err(anyhow!("Cannot set name for unknown user")) + } +} + +fn validate_message(text: String) -> Result { + if text.is_empty() { + Err(anyhow!("Messages must not be empty")) + } else { + Ok(text) + } +} + +#[spacetimedb(reducer)] +pub fn send_message(ctx: ReducerContext, text: String) -> Result<()> { + // Things to consider: + // - Rate-limit messages per-user. + // - Reject messages from unnamed users. + let text = validate_message(text)?; + Message::insert(Message { + sender: ctx.sender, + text, + sent: ctx.timestamp, + }); + Ok(()) +} diff --git a/sdks/csharp/src/Identity.cs b/sdks/csharp/src/Identity.cs index 90a37cd4b62..0251a3f931d 100644 --- a/sdks/csharp/src/Identity.cs +++ b/sdks/csharp/src/Identity.cs @@ -71,9 +71,9 @@ public override int GetHashCode() return BitConverter.ToInt32(bytes, 0); } - public override string ToString() - { - return string.Concat(bytes.Select(b => b.ToString("x2"))); + public override string ToString() + { + return string.Concat(bytes.Select(b => b.ToString("x2"))); } } } From b08a03eb55eeea52b40181cd5ba8894b251e5e1f Mon Sep 17 00:00:00 2001 From: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Date: Thu, 12 Oct 2023 09:28:02 -0400 Subject: [PATCH 054/223] README.md and License.txt updates (#53) * Update README.md * Add license.txt * Rename * Add LICENSE.txt with proper case --------- Co-authored-by: Derek Brinkmann --- sdks/csharp/LICENSE.txt | 177 ++++++++++++++++++++++++++++++++++++++++ sdks/csharp/README.md | 141 ++++++++++++++++++++++++++++++-- 2 files changed, 309 insertions(+), 9 deletions(-) create mode 100644 sdks/csharp/LICENSE.txt diff --git a/sdks/csharp/LICENSE.txt b/sdks/csharp/LICENSE.txt new file mode 100644 index 00000000000..4a459866a57 --- /dev/null +++ b/sdks/csharp/LICENSE.txt @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 111635efdfa..301334ae876 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -1,19 +1,142 @@ # SpacetimeDB SDK for C# -The SpacetimeDB SDK is a software development kit (SDK) designed to simplify the interaction with SpacetimeDB server modules. +## Overview -## Key Features +This repository contains the [C#](https://learn.microsoft.com/en-us/dotnet/csharp/) SDK for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. -### Connection Management +## Documentation -The SDK simplifies the process of establishing and managing connections to the SpacetimeDB module. Developers can establish secure WebSocket connections, enabling real-time communication with the module. +The C# SDK has a [Quick Start](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-quickstart-guide) guide and a [Reference](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-reference). -### Local Client Cache +## Installation -By subscribing to a set of queries, the SDK will keep a local cache of rows that match the subscribed queries. SpacetimeDB generates C# files that allow you to iterate throught these tables and filter on specific columns. +The SDK is available as a [NuGet Package](https://www.nuget.org/packages/SpacetimeDB.ClientSDK). To install it, follow these steps: -### Transaction and Row Update Events +1. Open the NuGet package manager in Visual Studio. +2. Search for `SpacetimeDB.ClientSDK`. +3. Click the install button. + +Alternatively, it can be installed on the command line using the `dotnet` command: + +```bash +dotnet add package SpacetimeDB.ClientSDK +``` + +## Usage + +### Create the SpacetimeDB Client + +To create a SpacetimeDB client, you need to create an instance of the `SpacetimeDBClient` class. The `SpacetimeDBClient` constructor takes the `module_bindings` folder that contains the auto-generated files as a parameter. The `module_bindings` folder is generated by the CLI generate command. + +```csharp +using SpacetimeDB; + +// create the client, pass in a logger to see debug messages +SpacetimeDBClient.CreateInstance(new ConsoleLogger()); +``` + +### Connecting to SpacetimeDB + +To connect to SpacetimeDB, you need to call the `Connect` method on the `SpacetimeDBClient` class. The `Connect` method takes the following parameters: + +- `token`: The authentication token to use to connect to SpacetimeDB. This token is generated by the backend code and is used to authenticate the client. +- `hostName`: The hostname of the SpacetimeDB server. This is the same hostname that you use to connect to the SpacetimeDB web interface. +- `moduleAddress`: The address of the module to connect to. This is the same address that you use to connect to the SpacetimeDB web interface. +- `sslEnabled`: Whether to use SSL to connect to SpacetimeDB. This is the same value that you use to connect to the SpacetimeDB web interface. + +Example: + +```csharp +using SpacetimeDB; + +SpacetimeDBClient.instance.Connect(TOKEN, HOST, DBNAME, SSL_ENABLED); +``` + +### AuthToken optional helper class + +The `AuthToken` class is a helper class that can be used to store the local client's authentication token locally to your user's home directory. + +```csharp +using SpacetimeDB; + +AuthToken.Init(".spacetime_csharp_quickstart"); + +SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME, SSL_ENABLED); + +void OnIdentityReceived(string authToken, Identity identity) +{ + local_identity = identity; + AuthToken.SaveToken(authToken); +} +SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; +``` + +### Subscribing to tables + +To subscribe to a table, you need to call the `Subscribe` method on the `SpacetimeDBClient` class. The `Subscribe` method takes a list of queries as a parameter. The queries are the same queries that you use to subscribe to tables in the SpacetimeDB web interface. + +### Listening to events + +To listen to events, you need to register callbacks on the `SpacetimeDBClient` class. The following callbacks are available: + +- `onConnect`: Called when the client connects to SpacetimeDB. +- `onConnectError`: Called when the client fails to connect to SpacetimeDB. +- `onDisconnect`: Called when the client disconnects from SpacetimeDB. +- `onIdentityReceived`: Called when the client receives its identity from SpacetimeDB. +- `onSubscriptionApplied`: Called when the client receives the initial data from SpacetimeDB after subscribing to tables. + +You can register for row update events on a table. To do this, you need to register callbacks on the table class. The following callbacks are available: + +- `OnInsert`: Called when a row is inserted into the table. +- `OnUpdate`: Called when a row is updated in the table. +- `OnBeforeDelete`: Called before a row is deleted from the table. +- `OnDelete`: Called when a row is deleted from the table. +- `OnRowUpdate`: Called when a row is inserted, updated, or deleted from the table. + +Example: + +```csharp +using SpacetimeDB.Types; + +PlayerComponent.OnInsert += PlayerComponent_OnInsert; +PlayerComponent.OnUpdate += PlayerComponent_OnUpdate; +PlayerComponent.OnDelete += PlayerComponent_OnDelete; +PlayerComponent.OnBeforeDelete += PlayerComponent_OnBeforeDelete; +PlayerComponent.OnRowUpdate += PlayerComponent_OnRowUpdate; +``` + +You can register for reducer call updates as well. + +- `OnREDUCEREvent`: Called when a reducer call is received from SpacetimeDB. (If a) you are subscribed to the table that the reducer modifies or b) You called the reducer and it failed) + +Example: + +```csharp +using SpacetimeDB.Types; + +Reducer.OnMovePlayerEvent += Reducer_OnMovePlayerEvent; +``` + +### Accessing the client cache + +The client cache is a local cache of the data that the client has received from SpacetimeDB. The client cache is automatically updated when the client receives updates from SpacetimeDB. + +When you run the CLI generate command, SpacetimeDB will automatically generate a class for each table in your database. These classes are generated in the `SpacetimeDB.Types` namespace. Each class contains a set of static methods that allow you to query the client cache. The following methods are available: + +- `FilterByCOLUMN`: Filters the table by the specified column value. +- `Iter`: Returns an iterator over the table. +- `Count`: Returns the number of rows in the table. + +### Calling Reducers + +To call a reducer, you need to call the autogenerated method on the `Reducer` class. The autogenerated method takes the reducer arguments as parameters. The reducer arguments are the same arguments that are expected in your server module. + +Example: + +```csharp +using SpacetimeDB.Types; + +Reducer.MovePlayer(new StdbVector2(0.0f, 0.0f), new StdbVector2(1.0f, 1.0f)); +``` -Register for transaction and row update events. -Full documentation can be found on the [SpacetimeDB](spacetimedb.com) website. From 102061f5fd280f776c1341ea0dcade99ef0cff06 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:54:57 -0500 Subject: [PATCH 055/223] Release v0.7.0-beta (#56) * One-off query support (#49) * SpacetimeDBURI argument in place of host and ssl enabled bool (#52) * SpacetimeDBURI argument in place of host and ssl enabled bool * Small cleanup --------- Co-authored-by: John Detter * Add support for client address; re-run `spacetime generate` for quickstart client (#54) * README.md and License.txt updates (#53) * Update README.md * Add license.txt * Rename * Add LICENSE.txt with proper case --------- Co-authored-by: Derek Brinkmann * Add support for client address; re-run `spacetime generate` for quickstart client Re: https://github.com/clockworklabs/SpacetimeDB/pull/299 --------- Co-authored-by: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Co-authored-by: Derek Brinkmann * Making Quickstart Work Again (#57) * Packaged nuget package, quickstart is now working again * Reset DBNAME --------- Co-authored-by: John Detter * OnUnhandledReducerError (#31) Co-authored-by: Steve Co-authored-by: Boppy --------- Co-authored-by: james gilles Co-authored-by: dbrinkmanncw <109690865+dbrinkmanncw@users.noreply.github.com> Co-authored-by: John Detter Co-authored-by: Phoebe Goldman Co-authored-by: Derek Brinkmann Co-authored-by: SteveBoytsun <100594800+SteveBoytsun@users.noreply.github.com> Co-authored-by: Steve --- sdks/csharp/SpacetimeDBCSharpSDK.csproj | 4 +- .../examples/quickstart/client/Program.cs | 392 ++-- .../client/module_bindings/Message.cs | 7 - .../client/module_bindings/ReducerEvent.cs | 4 +- .../module_bindings/ReducerJsonSettings.cs | 13 + .../module_bindings/SendMessageReducer.cs | 7 +- .../client/module_bindings/SetNameReducer.cs | 7 +- .../quickstart/client/module_bindings/User.cs | 10 + .../examples/quickstart/server/Cargo.lock | 104 +- .../examples/quickstart/server/Cargo.toml | 2 +- sdks/csharp/src/Address.cs | 89 + sdks/csharp/src/ClientApi.cs | 2081 ++++++++++++++++- sdks/csharp/src/ClientCache.cs | 12 + sdks/csharp/src/SpacetimeDBClient.cs | 122 +- sdks/csharp/src/Stubs.cs | 6 +- sdks/csharp/src/WebSocket.cs | 21 +- 16 files changed, 2568 insertions(+), 313 deletions(-) create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs create mode 100644 sdks/csharp/src/Address.cs diff --git a/sdks/csharp/SpacetimeDBCSharpSDK.csproj b/sdks/csharp/SpacetimeDBCSharpSDK.csproj index 181ac417016..af27d9f8a8f 100644 --- a/sdks/csharp/SpacetimeDBCSharpSDK.csproj +++ b/sdks/csharp/SpacetimeDBCSharpSDK.csproj @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/SpacetimeDBCSharpSDK - 0.6.0 - 0.6.0 + 0.7.0 + 0.7.0 diff --git a/sdks/csharp/examples/quickstart/client/Program.cs b/sdks/csharp/examples/quickstart/client/Program.cs index bf564ab9ae1..55074f3becf 100644 --- a/sdks/csharp/examples/quickstart/client/Program.cs +++ b/sdks/csharp/examples/quickstart/client/Program.cs @@ -1,196 +1,196 @@ -using SpacetimeDB; -using SpacetimeDB.Types; -using System.Collections.Concurrent; - -// our local client SpacetimeDB identity -Identity? local_identity = null; -// declare a thread safe queue to store commands in format (command, args) -ConcurrentQueue<(string, string)> input_queue = new ConcurrentQueue<(string, string)>(); -// declare a threadsafe cancel token to cancel the process loop -CancellationTokenSource cancel_token = new CancellationTokenSource(); - -void Main() -{ - AuthToken.Init(".spacetime_csharp_quickstart"); - - // create the client, pass in a logger to see debug messages - SpacetimeDBClient.CreateInstance(new ConsoleLogger()); - - RegisterCallbacks(); - - // spawn a thread to call process updates and process commands - var thread = new Thread(ProcessThread); - thread.Start(); - - InputLoop(); - - cancel_token.Cancel(); - thread.Join(); -} - -void RegisterCallbacks() -{ - SpacetimeDBClient.instance.onConnect += OnConnect; - SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; - SpacetimeDBClient.instance.onSubscriptionApplied += OnSubscriptionApplied; - - User.OnInsert += User_OnInsert; - User.OnUpdate += User_OnUpdate; - - Message.OnInsert += Message_OnInsert; - - Reducer.OnSetNameEvent += Reducer_OnSetNameEvent; - Reducer.OnSendMessageEvent += Reducer_OnSendMessageEvent; -} - -string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()!.Substring(0, 8); - -void User_OnInsert(User insertedValue, ReducerEvent dbEvent) -{ - if (insertedValue.Online) - { - Console.WriteLine($"{UserNameOrIdentity(insertedValue)} is online"); - } -} - -void User_OnUpdate(User oldValue, User newValue, ReducerEvent dbEvent) -{ - if (oldValue.Name != newValue.Name) - { - Console.WriteLine($"{UserNameOrIdentity(oldValue)} renamed to {newValue.Name}"); - } - if (oldValue.Online != newValue.Online) - { - if (newValue.Online) - { - Console.WriteLine($"{UserNameOrIdentity(newValue)} connected."); - } - else - { - Console.WriteLine($"{UserNameOrIdentity(newValue)} disconnected."); - } - } -} - -void PrintMessage(Message message) -{ - var sender = User.FilterByIdentity(message.Sender); - var senderName = "unknown"; - if (sender != null) - { - senderName = UserNameOrIdentity(sender); - } - - Console.WriteLine($"{senderName}: {message.Text}"); -} - -void Message_OnInsert(Message insertedValue, ReducerEvent dbEvent) -{ - if (dbEvent != null) - { - PrintMessage(insertedValue); - } -} - -void Reducer_OnSetNameEvent(ReducerEvent reducerEvent, string name) -{ - if (reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) - { - Console.Write($"Failed to change name to {name}"); - } -} - -void Reducer_OnSendMessageEvent(ReducerEvent reducerEvent, string text) -{ - if (reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) - { - Console.Write($"Failed to send message {text}"); - } -} - -void OnConnect() -{ - SpacetimeDBClient.instance.Subscribe(new List { "SELECT * FROM User", "SELECT * FROM Message" }); -} - -void OnIdentityReceived(string authToken, Identity identity) -{ - local_identity = identity; - AuthToken.SaveToken(authToken); -} - -void PrintMessagesInOrder() -{ - foreach (Message message in Message.Iter().OrderBy(item => item.Sent)) - { - PrintMessage(message); - } -} - -void OnSubscriptionApplied() -{ - Console.WriteLine("Connected"); - PrintMessagesInOrder(); -} - -const string HOST = "localhost:3000"; -const string DBNAME = "chat2"; -const bool SSL_ENABLED = false; - -void ProcessThread() -{ - SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME, SSL_ENABLED); - - // loop until cancellation token - while (!cancel_token.IsCancellationRequested) - { - SpacetimeDBClient.instance.Update(); - - ProcessCommands(); - - Thread.Sleep(100); - } - - SpacetimeDBClient.instance.Close(); -} - -void InputLoop() -{ - while (true) - { - var input = Console.ReadLine(); - if(input == null) - { - break; - } - - if(input.StartsWith("/name ")) - { - input_queue.Enqueue(("name", input.Substring(6))); - continue; - } - else - { - input_queue.Enqueue(("message", input)); - } - } -} - -void ProcessCommands() -{ - // process input queue commands - while (input_queue.TryDequeue(out var command)) - { - switch (command.Item1) - { - case "message": - Reducer.SendMessage(command.Item2); - break; - case "name": - Reducer.SetName(command.Item2); - break; - } - } -} - -Main(); \ No newline at end of file +using SpacetimeDB; +using SpacetimeDB.Types; +using System.Collections.Concurrent; + +// our local client SpacetimeDB identity +Identity? local_identity = null; +// declare a thread safe queue to store commands in format (command, args) +ConcurrentQueue<(string,string)> input_queue = new ConcurrentQueue<(string, string)>(); +// declare a threadsafe cancel token to cancel the process loop +CancellationTokenSource cancel_token = new CancellationTokenSource(); + +void Main() +{ + AuthToken.Init(".spacetime_csharp_quickstart"); + + // create the client, pass in a logger to see debug messages + SpacetimeDBClient.CreateInstance(new ConsoleLogger()); + + RegisterCallbacks(); + + // spawn a thread to call process updates and process commands + var thread = new Thread(ProcessThread); + thread.Start(); + + InputLoop(); + + // this signals the ProcessThread to stop + cancel_token.Cancel(); + thread.Join(); +} + +void RegisterCallbacks() +{ + SpacetimeDBClient.instance.onConnect += OnConnect; + SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; + SpacetimeDBClient.instance.onSubscriptionApplied += OnSubscriptionApplied; + + User.OnInsert += User_OnInsert; + User.OnUpdate += User_OnUpdate; + + Message.OnInsert += Message_OnInsert; + + Reducer.OnSetNameEvent += Reducer_OnSetNameEvent; + Reducer.OnSendMessageEvent += Reducer_OnSendMessageEvent; +} + +string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()!.Substring(0, 8); + +void User_OnInsert(User insertedValue, ReducerEvent? dbEvent) +{ + if(insertedValue.Online) + { + Console.WriteLine($"{UserNameOrIdentity(insertedValue)} is online"); + } +} + +void User_OnUpdate(User oldValue, User newValue, ReducerEvent dbEvent) +{ + if(oldValue.Name != newValue.Name) + { + Console.WriteLine($"{UserNameOrIdentity(oldValue)} renamed to {newValue.Name}"); + } + if(oldValue.Online != newValue.Online) + { + if(newValue.Online) + { + Console.WriteLine($"{UserNameOrIdentity(newValue)} connected."); + } + else + { + Console.WriteLine($"{UserNameOrIdentity(newValue)} disconnected."); + } + } +} + +void PrintMessage(Message message) +{ + var sender = User.FilterByIdentity(message.Sender); + var senderName = "unknown"; + if(sender != null) + { + senderName = UserNameOrIdentity(sender); + } + + Console.WriteLine($"{senderName}: {message.Text}"); +} + +void Message_OnInsert(Message insertedValue, ReducerEvent? dbEvent) +{ + if(dbEvent != null) + { + PrintMessage(insertedValue); + } +} + +void Reducer_OnSetNameEvent(ReducerEvent reducerEvent, string name) +{ + if(reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) + { + Console.Write($"Failed to change name to {name}"); + } +} + +void Reducer_OnSendMessageEvent(ReducerEvent reducerEvent, string text) +{ + if (reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) + { + Console.Write($"Failed to send message {text}"); + } +} + +void OnConnect() +{ + SpacetimeDBClient.instance.Subscribe(new List { "SELECT * FROM User", "SELECT * FROM Message" }); +} + +void OnIdentityReceived(string authToken, Identity identity, Address _address) +{ + local_identity = identity; + AuthToken.SaveToken(authToken); +} + +void PrintMessagesInOrder() +{ + foreach (Message message in Message.Iter().OrderBy(item => item.Sent)) + { + PrintMessage(message); + } +} + +void OnSubscriptionApplied() +{ + Console.WriteLine("Connected"); + PrintMessagesInOrder(); +} + +const string HOST = "http://localhost:3000"; +const string DBNAME = "chatqs"; + +void ProcessThread() +{ + SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME); + + // loop until cancellation token + while (!cancel_token.IsCancellationRequested) + { + SpacetimeDBClient.instance.Update(); + + ProcessCommands(); + + Thread.Sleep(100); + } + + SpacetimeDBClient.instance.Close(); +} + +void InputLoop() +{ + while (true) + { + var input = Console.ReadLine(); + if(input == null) + { + break; + } + + if(input.StartsWith("/name ")) + { + input_queue.Enqueue(("name", input.Substring(6))); + continue; + } + else + { + input_queue.Enqueue(("message", input)); + } + } +} + +void ProcessCommands() +{ + // process input queue commands + while (input_queue.TryDequeue(out var command)) + { + switch (command.Item1) + { + case "message": + Reducer.SendMessage(command.Item2); + break; + case "name": + Reducer.SetName(command.Item2); + break; + } + } +} + +Main(); diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs index 223f57b4c39..eb383376d3a 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs @@ -107,11 +107,9 @@ public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, Spacetime } public delegate void InsertEventHandler(Message insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); - public delegate void UpdateEventHandler(Message oldValue, Message newValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void DeleteEventHandler(Message deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void RowUpdateEventHandler(SpacetimeDBClient.TableOp op, Message oldValue, Message newValue, SpacetimeDB.Types.ReducerEvent dbEvent); public static event InsertEventHandler OnInsert; - public static event UpdateEventHandler OnUpdate; public static event DeleteEventHandler OnBeforeDelete; public static event DeleteEventHandler OnDelete; public static event RowUpdateEventHandler OnRowUpdate; @@ -121,11 +119,6 @@ public static void OnInsertEvent(object newValue, ClientApi.Event dbEvent) OnInsert?.Invoke((Message)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); } - public static void OnUpdateEvent(object oldValue, object newValue, ClientApi.Event dbEvent) - { - OnUpdate?.Invoke((Message)oldValue,(Message)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } - public static void OnBeforeDeleteEvent(object oldValue, ClientApi.Event dbEvent) { OnBeforeDelete?.Invoke((Message)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs index 344e6e383ef..57d56bef14d 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs @@ -19,8 +19,8 @@ public partial class ReducerEvent : ReducerEventBase { public ReducerType Reducer { get; private set; } - public ReducerEvent(ReducerType reducer, string reducerName, ulong timestamp, SpacetimeDB.Identity identity, string errMessage, ClientApi.Event.Types.Status status, object args) - : base(reducerName, timestamp, identity, errMessage, status, args) + public ReducerEvent(ReducerType reducer, string reducerName, ulong timestamp, SpacetimeDB.Identity identity, SpacetimeDB.Address? callerAddress, string errMessage, ClientApi.Event.Types.Status status, object args) + : base(reducerName, timestamp, identity, callerAddress, errMessage, status, args) { Reducer = reducer; } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs new file mode 100644 index 00000000000..d42b1a5d46e --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs @@ -0,0 +1,13 @@ +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + public partial class Reducer + { + private static Newtonsoft.Json.JsonSerializerSettings _settings = new Newtonsoft.Json.JsonSerializerSettings + { + Converters = { new SpacetimeDB.SomeWrapperConverter(), new SpacetimeDB.EnumWrapperConverter() }, + ContractResolver = new SpacetimeDB.JsonContractResolver(), + }; + } +} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs index 9b37c0f9f70..931beb9a50b 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs @@ -20,11 +20,6 @@ public static void SendMessage(string text) fn = "send_message", args = _argArray, }; - Newtonsoft.Json.JsonSerializerSettings _settings = new Newtonsoft.Json.JsonSerializerSettings - { - Converters = { new SpacetimeDB.SomeWrapperConverter(), new SpacetimeDB.EnumWrapperConverter() }, - ContractResolver = new SpacetimeDB.JsonContractResolver(), - }; SpacetimeDBClient.instance.InternalCallReducer(Newtonsoft.Json.JsonConvert.SerializeObject(_message, _settings)); } @@ -54,7 +49,7 @@ public static void SendMessageDeserializeEventArgs(ClientApi.Event dbEvent) using var reader = new System.IO.BinaryReader(ms); var args_0_value = SpacetimeDB.SATS.AlgebraicValue.Deserialize(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String), reader); args.Text = args_0_value.AsString(); - dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.SendMessage, "send_message", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), dbEvent.Message, dbEvent.Status, args); + dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.SendMessage, "send_message", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), Address.From(dbEvent.CallerAddress.ToByteArray()), dbEvent.Message, dbEvent.Status, args); } } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs index c4806057d4d..d97415b5fc8 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs @@ -20,11 +20,6 @@ public static void SetName(string name) fn = "set_name", args = _argArray, }; - Newtonsoft.Json.JsonSerializerSettings _settings = new Newtonsoft.Json.JsonSerializerSettings - { - Converters = { new SpacetimeDB.SomeWrapperConverter(), new SpacetimeDB.EnumWrapperConverter() }, - ContractResolver = new SpacetimeDB.JsonContractResolver(), - }; SpacetimeDBClient.instance.InternalCallReducer(Newtonsoft.Json.JsonConvert.SerializeObject(_message, _settings)); } @@ -54,7 +49,7 @@ public static void SetNameDeserializeEventArgs(ClientApi.Event dbEvent) using var reader = new System.IO.BinaryReader(ms); var args_0_value = SpacetimeDB.SATS.AlgebraicValue.Deserialize(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String), reader); args.Name = args_0_value.AsString(); - dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.SetName, "set_name", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), dbEvent.Message, dbEvent.Status, args); + dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.SetName, "set_name", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), Address.From(dbEvent.CallerAddress.ToByteArray()), dbEvent.Message, dbEvent.Status, args); } } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs index b50a45027c9..503340016e8 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs @@ -100,6 +100,16 @@ public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, Spacetime return SpacetimeDB.SATS.AlgebraicValue.Compare(t.product.elements[0].algebraicType, primaryColumnValue1, primaryColumnValue2); } + public static SpacetimeDB.SATS.AlgebraicValue GetPrimaryKeyValue(SpacetimeDB.SATS.AlgebraicValue v) + { + return v.AsProductValue().elements[0]; + } + + public static SpacetimeDB.SATS.AlgebraicType GetPrimaryKeyType(SpacetimeDB.SATS.AlgebraicType t) + { + return t.product.elements[0].algebraicType; + } + public delegate void InsertEventHandler(User insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void UpdateEventHandler(User oldValue, User newValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void DeleteEventHandler(User deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); diff --git a/sdks/csharp/examples/quickstart/server/Cargo.lock b/sdks/csharp/examples/quickstart/server/Cargo.lock index 9174e943226..2699863f7c3 100644 --- a/sdks/csharp/examples/quickstart/server/Cargo.lock +++ b/sdks/csharp/examples/quickstart/server/Cargo.lock @@ -2,11 +2,29 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "anyhow" version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +dependencies = [ + "backtrace", +] [[package]] name = "approx" @@ -29,6 +47,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -38,6 +71,21 @@ dependencies = [ "generic-array", ] +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "cpufeatures" version = "0.2.9" @@ -105,6 +153,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "heck" version = "0.4.1" @@ -153,6 +207,21 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -162,6 +231,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -186,6 +264,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "scoped-tls" version = "1.0.1" @@ -213,7 +297,9 @@ dependencies = [ [[package]] name = "spacetimedb" -version = "0.5.0" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb2607c4aeda83c3568a5e371bc0a1caa0aa104732987814358bb7e062cf6ccf" dependencies = [ "log", "once_cell", @@ -225,7 +311,9 @@ dependencies = [ [[package]] name = "spacetimedb-bindings-macro" -version = "0.5.0" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6a9b4b143d79933f5e7f00d074ebc391d4f152ae2dd56be6beb1755532d7f6" dependencies = [ "humantime", "proc-macro2", @@ -235,11 +323,15 @@ dependencies = [ [[package]] name = "spacetimedb-bindings-sys" -version = "0.5.0" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6448feac3c8eea403c8cb1cf315958aec4e57c713c002ea8b9064fab9fea9fd9" [[package]] name = "spacetimedb-lib" -version = "0.5.0" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8297e4e5843d346bd7844366e3cdf3b1dfd9259b466166d4e9c8588106b967b5" dependencies = [ "anyhow", "enum-as-inner", @@ -253,7 +345,9 @@ dependencies = [ [[package]] name = "spacetimedb-sats" -version = "0.5.0" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98d414893befd6b19e874243334cb5709348aedc7eae01db7813b17f10583ab8" dependencies = [ "arrayvec", "decorum", diff --git a/sdks/csharp/examples/quickstart/server/Cargo.toml b/sdks/csharp/examples/quickstart/server/Cargo.toml index d799f635699..bf8735590be 100644 --- a/sdks/csharp/examples/quickstart/server/Cargo.toml +++ b/sdks/csharp/examples/quickstart/server/Cargo.toml @@ -9,6 +9,6 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -spacetimedb = { path = "../../../../spacetimedb/crates/bindings" } +spacetimedb = "0.7" log = "0.4" anyhow = "1.0" diff --git a/sdks/csharp/src/Address.cs b/sdks/csharp/src/Address.cs new file mode 100644 index 00000000000..0a0ac37d857 --- /dev/null +++ b/sdks/csharp/src/Address.cs @@ -0,0 +1,89 @@ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using SpacetimeDB.SATS; + +namespace SpacetimeDB +{ + public struct Address : IEquatable
    + { + private byte[] bytes; + + public static int SIZE = 16; + + public byte[] Bytes => bytes; + + public static AlgebraicType GetAlgebraicType() + { + return new AlgebraicType + { + type = AlgebraicType.Type.Builtin, + builtin = new BuiltinType + { + type = BuiltinType.Type.Array, + arrayType = new AlgebraicType + { + type = AlgebraicType.Type.Builtin, + builtin = new BuiltinType + { + type = BuiltinType.Type.U8 + } + } + } + }; + } + + public static explicit operator Address(AlgebraicValue v) => new Address + { + bytes = v.AsBytes(), + }; + + public static Address? From(byte[] bytes) + { + if (bytes.All(b => b == 0)) { + return null; + } + return new Address + { + bytes = bytes, + }; + } + + public bool Equals(Address other) + { + return bytes.SequenceEqual(other.bytes); + } + + public override bool Equals(object o) + { + return o is Address other && Equals(other); + } + + public static bool operator ==(Address a, Address b) => a.Equals(b); + public static bool operator !=(Address a, Address b) => !a.Equals(b); + + public static Address Random() { + Random rnd = new Random(); + var bytes = new byte[16]; + rnd.NextBytes(bytes); + return new Address{ bytes = bytes, }; + } + + public override int GetHashCode() + { + if (bytes == null) + { + throw new InvalidOperationException("Cannot hash on null bytes."); + } + + return BitConverter.ToInt32(bytes, 0); + } + + public override string ToString() + { + return string.Concat(bytes.Select(b => b.ToString("x2"))); + } + } +} diff --git a/sdks/csharp/src/ClientApi.cs b/sdks/csharp/src/ClientApi.cs index e6604e9109a..a8b3ec3460a 100644 --- a/sdks/csharp/src/ClientApi.cs +++ b/sdks/csharp/src/ClientApi.cs @@ -2,7 +2,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: client_api.proto // -#pragma warning disable 1591, 0612, 3021 +#pragma warning disable 1591, 0612, 3021, 8981 #region Designer generated code using pb = global::Google.Protobuf; @@ -24,43 +24,57 @@ public static partial class ClientApiReflection { static ClientApiReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChBjbGllbnRfYXBpLnByb3RvEgpjbGllbnRfYXBpIpUCCgdNZXNzYWdlEjAK", + "ChBjbGllbnRfYXBpLnByb3RvEgpjbGllbnRfYXBpIrEDCgdNZXNzYWdlEjAK", "DGZ1bmN0aW9uQ2FsbBgBIAEoCzIYLmNsaWVudF9hcGkuRnVuY3Rpb25DYWxs", "SAASPAoSc3Vic2NyaXB0aW9uVXBkYXRlGAIgASgLMh4uY2xpZW50X2FwaS5T", "dWJzY3JpcHRpb25VcGRhdGVIABIiCgVldmVudBgDIAEoCzIRLmNsaWVudF9h", "cGkuRXZlbnRIABI6ChF0cmFuc2FjdGlvblVwZGF0ZRgEIAEoCzIdLmNsaWVu", "dF9hcGkuVHJhbnNhY3Rpb25VcGRhdGVIABIyCg1pZGVudGl0eVRva2VuGAUg", - "ASgLMhkuY2xpZW50X2FwaS5JZGVudGl0eVRva2VuSABCBgoEdHlwZSIwCg1J", - "ZGVudGl0eVRva2VuEhAKCGlkZW50aXR5GAEgASgMEg0KBXRva2VuGAIgASgJ", - "IjEKDEZ1bmN0aW9uQ2FsbBIPCgdyZWR1Y2VyGAEgASgJEhAKCGFyZ0J5dGVz", - "GAIgASgMIpkCCgVFdmVudBIRCgl0aW1lc3RhbXAYASABKAQSFgoOY2FsbGVy", - "SWRlbnRpdHkYAiABKAwSLgoMZnVuY3Rpb25DYWxsGAMgASgLMhguY2xpZW50", - "X2FwaS5GdW5jdGlvbkNhbGwSKAoGc3RhdHVzGAQgASgOMhguY2xpZW50X2Fw", - "aS5FdmVudC5TdGF0dXMSDwoHbWVzc2FnZRgFIAEoCRIaChJlbmVyZ3lfcXVh", - "bnRhX3VzZWQYBiABKAMSJgoeaG9zdF9leGVjdXRpb25fZHVyYXRpb25fbWlj", - "cm9zGAcgASgEIjYKBlN0YXR1cxINCgljb21taXR0ZWQQABIKCgZmYWlsZWQQ", - "ARIRCg1vdXRfb2ZfZW5lcmd5EAIiQwoSU3Vic2NyaXB0aW9uVXBkYXRlEi0K", - "DHRhYmxlVXBkYXRlcxgBIAMoCzIXLmNsaWVudF9hcGkuVGFibGVVcGRhdGUi", - "bAoLVGFibGVVcGRhdGUSDwoHdGFibGVJZBgBIAEoDRIRCgl0YWJsZU5hbWUY", - "AiABKAkSOQoSdGFibGVSb3dPcGVyYXRpb25zGAMgAygLMh0uY2xpZW50X2Fw", - "aS5UYWJsZVJvd09wZXJhdGlvbiKSAQoRVGFibGVSb3dPcGVyYXRpb24SNwoC", - "b3AYASABKA4yKy5jbGllbnRfYXBpLlRhYmxlUm93T3BlcmF0aW9uLk9wZXJh", - "dGlvblR5cGUSDgoGcm93X3BrGAIgASgMEgsKA3JvdxgDIAEoDCInCg1PcGVy", - "YXRpb25UeXBlEgoKBkRFTEVURRAAEgoKBklOU0VSVBABInEKEVRyYW5zYWN0", - "aW9uVXBkYXRlEiAKBWV2ZW50GAEgASgLMhEuY2xpZW50X2FwaS5FdmVudBI6", - "ChJzdWJzY3JpcHRpb25VcGRhdGUYAiABKAsyHi5jbGllbnRfYXBpLlN1YnNj", - "cmlwdGlvblVwZGF0ZWIGcHJvdG8z")); + "ASgLMhkuY2xpZW50X2FwaS5JZGVudGl0eVRva2VuSAASKgoJc3Vic2NyaWJl", + "GAYgASgLMhUuY2xpZW50X2FwaS5TdWJzY3JpYmVIABIuCgtvbmVPZmZRdWVy", + "eRgHIAEoCzIXLmNsaWVudF9hcGkuT25lT2ZmUXVlcnlIABI+ChNvbmVPZmZR", + "dWVyeVJlc3BvbnNlGAggASgLMh8uY2xpZW50X2FwaS5PbmVPZmZRdWVyeVJl", + "c3BvbnNlSABCBgoEdHlwZSJBCg1JZGVudGl0eVRva2VuEhAKCGlkZW50aXR5", + "GAEgASgMEg0KBXRva2VuGAIgASgJEg8KB2FkZHJlc3MYAyABKAwiMQoMRnVu", + "Y3Rpb25DYWxsEg8KB3JlZHVjZXIYASABKAkSEAoIYXJnQnl0ZXMYAiABKAwi", + "IgoJU3Vic2NyaWJlEhUKDXF1ZXJ5X3N0cmluZ3MYASADKAkisAIKBUV2ZW50", + "EhEKCXRpbWVzdGFtcBgBIAEoBBIWCg5jYWxsZXJJZGVudGl0eRgCIAEoDBIu", + "CgxmdW5jdGlvbkNhbGwYAyABKAsyGC5jbGllbnRfYXBpLkZ1bmN0aW9uQ2Fs", + "bBIoCgZzdGF0dXMYBCABKA4yGC5jbGllbnRfYXBpLkV2ZW50LlN0YXR1cxIP", + "CgdtZXNzYWdlGAUgASgJEhoKEmVuZXJneV9xdWFudGFfdXNlZBgGIAEoAxIm", + "Ch5ob3N0X2V4ZWN1dGlvbl9kdXJhdGlvbl9taWNyb3MYByABKAQSFQoNY2Fs", + "bGVyQWRkcmVzcxgIIAEoDCI2CgZTdGF0dXMSDQoJY29tbWl0dGVkEAASCgoG", + "ZmFpbGVkEAESEQoNb3V0X29mX2VuZXJneRACIkMKElN1YnNjcmlwdGlvblVw", + "ZGF0ZRItCgx0YWJsZVVwZGF0ZXMYASADKAsyFy5jbGllbnRfYXBpLlRhYmxl", + "VXBkYXRlImwKC1RhYmxlVXBkYXRlEg8KB3RhYmxlSWQYASABKA0SEQoJdGFi", + "bGVOYW1lGAIgASgJEjkKEnRhYmxlUm93T3BlcmF0aW9ucxgDIAMoCzIdLmNs", + "aWVudF9hcGkuVGFibGVSb3dPcGVyYXRpb24ikgEKEVRhYmxlUm93T3BlcmF0", + "aW9uEjcKAm9wGAEgASgOMisuY2xpZW50X2FwaS5UYWJsZVJvd09wZXJhdGlv", + "bi5PcGVyYXRpb25UeXBlEg4KBnJvd19waxgCIAEoDBILCgNyb3cYAyABKAwi", + "JwoNT3BlcmF0aW9uVHlwZRIKCgZERUxFVEUQABIKCgZJTlNFUlQQASJxChFU", + "cmFuc2FjdGlvblVwZGF0ZRIgCgVldmVudBgBIAEoCzIRLmNsaWVudF9hcGku", + "RXZlbnQSOgoSc3Vic2NyaXB0aW9uVXBkYXRlGAIgASgLMh4uY2xpZW50X2Fw", + "aS5TdWJzY3JpcHRpb25VcGRhdGUiNQoLT25lT2ZmUXVlcnkSEQoJbWVzc2Fn", + "ZUlkGAEgASgMEhMKC3F1ZXJ5U3RyaW5nGAIgASgJImAKE09uZU9mZlF1ZXJ5", + "UmVzcG9uc2USEQoJbWVzc2FnZUlkGAEgASgMEg0KBWVycm9yGAIgASgJEicK", + "BnRhYmxlcxgDIAMoCzIXLmNsaWVudF9hcGkuT25lT2ZmVGFibGUiLQoLT25l", + "T2ZmVGFibGUSEQoJdGFibGVOYW1lGAIgASgJEgsKA3JvdxgEIAMoDGIGcHJv", + "dG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Message), global::ClientApi.Message.Parser, new[]{ "FunctionCall", "SubscriptionUpdate", "Event", "TransactionUpdate", "IdentityToken" }, new[]{ "Type" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.IdentityToken), global::ClientApi.IdentityToken.Parser, new[]{ "Identity", "Token" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Message), global::ClientApi.Message.Parser, new[]{ "FunctionCall", "SubscriptionUpdate", "Event", "TransactionUpdate", "IdentityToken", "Subscribe", "OneOffQuery", "OneOffQueryResponse" }, new[]{ "Type" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.IdentityToken), global::ClientApi.IdentityToken.Parser, new[]{ "Identity", "Token", "Address" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.FunctionCall), global::ClientApi.FunctionCall.Parser, new[]{ "Reducer", "ArgBytes" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Event), global::ClientApi.Event.Parser, new[]{ "Timestamp", "CallerIdentity", "FunctionCall", "Status", "Message", "EnergyQuantaUsed", "HostExecutionDurationMicros" }, null, new[]{ typeof(global::ClientApi.Event.Types.Status) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Subscribe), global::ClientApi.Subscribe.Parser, new[]{ "QueryStrings" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Event), global::ClientApi.Event.Parser, new[]{ "Timestamp", "CallerIdentity", "FunctionCall", "Status", "Message", "EnergyQuantaUsed", "HostExecutionDurationMicros", "CallerAddress" }, null, new[]{ typeof(global::ClientApi.Event.Types.Status) }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.SubscriptionUpdate), global::ClientApi.SubscriptionUpdate.Parser, new[]{ "TableUpdates" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableUpdate), global::ClientApi.TableUpdate.Parser, new[]{ "TableId", "TableName", "TableRowOperations" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableRowOperation), global::ClientApi.TableRowOperation.Parser, new[]{ "Op", "RowPk", "Row" }, null, new[]{ typeof(global::ClientApi.TableRowOperation.Types.OperationType) }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TransactionUpdate), global::ClientApi.TransactionUpdate.Parser, new[]{ "Event", "SubscriptionUpdate" }, null, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TransactionUpdate), global::ClientApi.TransactionUpdate.Parser, new[]{ "Event", "SubscriptionUpdate" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQuery), global::ClientApi.OneOffQuery.Parser, new[]{ "MessageId", "QueryString" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQueryResponse), global::ClientApi.OneOffQueryResponse.Parser, new[]{ "MessageId", "Error", "Tables" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffTable), global::ClientApi.OneOffTable.Parser, new[]{ "TableName", "Row" }, null, null, null, null) })); } #endregion @@ -69,27 +83,35 @@ static ClientApiReflection() { #region Messages /// /////// Generic Message ////// - /// TODO: Theoretically this format could be replaced by TypeValue/TypeDef + /// TODO: Theoretically this format could be replaced by AlgebraicValue/AlgebraicType /// but I don't think we want to do that yet. /// TODO: Split this up into ServerBound and ClientBound if there's no overlap /// - public sealed partial class Message : pb::IMessage { + public sealed partial class Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Message()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[0]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public Message() { OnConstruction(); } @@ -97,6 +119,7 @@ public Message() { partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public Message(Message other) : this() { switch (other.TypeCase) { case TypeOneofCase.FunctionCall: @@ -114,19 +137,33 @@ public Message(Message other) : this() { case TypeOneofCase.IdentityToken: IdentityToken = other.IdentityToken.Clone(); break; + case TypeOneofCase.Subscribe: + Subscribe = other.Subscribe.Clone(); + break; + case TypeOneofCase.OneOffQuery: + OneOffQuery = other.OneOffQuery.Clone(); + break; + case TypeOneofCase.OneOffQueryResponse: + OneOffQueryResponse = other.OneOffQueryResponse.Clone(); + break; } _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public Message Clone() { return new Message(this); } /// Field number for the "functionCall" field. public const int FunctionCallFieldNumber = 1; + /// + /// client -> database, request a reducer run. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.FunctionCall FunctionCall { get { return typeCase_ == TypeOneofCase.FunctionCall ? (global::ClientApi.FunctionCall) type_ : null; } set { @@ -137,7 +174,12 @@ public Message Clone() { /// Field number for the "subscriptionUpdate" field. public const int SubscriptionUpdateFieldNumber = 2; + /// + /// database -> client, contained in `TransactionUpdate`, informs of changes to + /// subscribed rows. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.SubscriptionUpdate SubscriptionUpdate { get { return typeCase_ == TypeOneofCase.SubscriptionUpdate ? (global::ClientApi.SubscriptionUpdate) type_ : null; } set { @@ -148,7 +190,11 @@ public Message Clone() { /// Field number for the "event" field. public const int EventFieldNumber = 3; + /// + /// database -> client, contained in `TransactionUpdate`, describes a reducer run. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.Event Event { get { return typeCase_ == TypeOneofCase.Event ? (global::ClientApi.Event) type_ : null; } set { @@ -159,7 +205,11 @@ public Message Clone() { /// Field number for the "transactionUpdate" field. public const int TransactionUpdateFieldNumber = 4; + /// + /// database -> client, upon reducer run. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.TransactionUpdate TransactionUpdate { get { return typeCase_ == TypeOneofCase.TransactionUpdate ? (global::ClientApi.TransactionUpdate) type_ : null; } set { @@ -170,7 +220,11 @@ public Message Clone() { /// Field number for the "identityToken" field. public const int IdentityTokenFieldNumber = 5; + /// + /// database -> client, after connecting, to inform client of its identity. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.IdentityToken IdentityToken { get { return typeCase_ == TypeOneofCase.IdentityToken ? (global::ClientApi.IdentityToken) type_ : null; } set { @@ -179,6 +233,51 @@ public Message Clone() { } } + /// Field number for the "subscribe" field. + public const int SubscribeFieldNumber = 6; + /// + /// client -> database, register SQL queries on which to receive updates. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::ClientApi.Subscribe Subscribe { + get { return typeCase_ == TypeOneofCase.Subscribe ? (global::ClientApi.Subscribe) type_ : null; } + set { + type_ = value; + typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.Subscribe; + } + } + + /// Field number for the "oneOffQuery" field. + public const int OneOffQueryFieldNumber = 7; + /// + /// client -> database, send a one-off SQL query without establishing a subscription. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::ClientApi.OneOffQuery OneOffQuery { + get { return typeCase_ == TypeOneofCase.OneOffQuery ? (global::ClientApi.OneOffQuery) type_ : null; } + set { + type_ = value; + typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.OneOffQuery; + } + } + + /// Field number for the "oneOffQueryResponse" field. + public const int OneOffQueryResponseFieldNumber = 8; + /// + /// database -> client, return results to a one off SQL query. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::ClientApi.OneOffQueryResponse OneOffQueryResponse { + get { return typeCase_ == TypeOneofCase.OneOffQueryResponse ? (global::ClientApi.OneOffQueryResponse) type_ : null; } + set { + type_ = value; + typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.OneOffQueryResponse; + } + } + private object type_; /// Enum of possible cases for the "type" oneof. public enum TypeOneofCase { @@ -188,25 +287,32 @@ public enum TypeOneofCase { Event = 3, TransactionUpdate = 4, IdentityToken = 5, + Subscribe = 6, + OneOffQuery = 7, + OneOffQueryResponse = 8, } private TypeOneofCase typeCase_ = TypeOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TypeOneofCase TypeCase { get { return typeCase_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void ClearType() { typeCase_ = TypeOneofCase.None; type_ = null; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { return Equals(other as Message); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public bool Equals(Message other) { if (ReferenceEquals(other, null)) { return false; @@ -219,11 +325,15 @@ public bool Equals(Message other) { if (!object.Equals(Event, other.Event)) return false; if (!object.Equals(TransactionUpdate, other.TransactionUpdate)) return false; if (!object.Equals(IdentityToken, other.IdentityToken)) return false; + if (!object.Equals(Subscribe, other.Subscribe)) return false; + if (!object.Equals(OneOffQuery, other.OneOffQuery)) return false; + if (!object.Equals(OneOffQueryResponse, other.OneOffQueryResponse)) return false; if (TypeCase != other.TypeCase) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; if (typeCase_ == TypeOneofCase.FunctionCall) hash ^= FunctionCall.GetHashCode(); @@ -231,6 +341,9 @@ public override int GetHashCode() { if (typeCase_ == TypeOneofCase.Event) hash ^= Event.GetHashCode(); if (typeCase_ == TypeOneofCase.TransactionUpdate) hash ^= TransactionUpdate.GetHashCode(); if (typeCase_ == TypeOneofCase.IdentityToken) hash ^= IdentityToken.GetHashCode(); + if (typeCase_ == TypeOneofCase.Subscribe) hash ^= Subscribe.GetHashCode(); + if (typeCase_ == TypeOneofCase.OneOffQuery) hash ^= OneOffQuery.GetHashCode(); + if (typeCase_ == TypeOneofCase.OneOffQueryResponse) hash ^= OneOffQueryResponse.GetHashCode(); hash ^= (int) typeCase_; if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); @@ -239,12 +352,17 @@ public override int GetHashCode() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (typeCase_ == TypeOneofCase.FunctionCall) { output.WriteRawTag(10); output.WriteMessage(FunctionCall); @@ -265,12 +383,68 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(42); output.WriteMessage(IdentityToken); } + if (typeCase_ == TypeOneofCase.Subscribe) { + output.WriteRawTag(50); + output.WriteMessage(Subscribe); + } + if (typeCase_ == TypeOneofCase.OneOffQuery) { + output.WriteRawTag(58); + output.WriteMessage(OneOffQuery); + } + if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { + output.WriteRawTag(66); + output.WriteMessage(OneOffQueryResponse); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (typeCase_ == TypeOneofCase.FunctionCall) { + output.WriteRawTag(10); + output.WriteMessage(FunctionCall); + } + if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { + output.WriteRawTag(18); + output.WriteMessage(SubscriptionUpdate); + } + if (typeCase_ == TypeOneofCase.Event) { + output.WriteRawTag(26); + output.WriteMessage(Event); + } + if (typeCase_ == TypeOneofCase.TransactionUpdate) { + output.WriteRawTag(34); + output.WriteMessage(TransactionUpdate); + } + if (typeCase_ == TypeOneofCase.IdentityToken) { + output.WriteRawTag(42); + output.WriteMessage(IdentityToken); + } + if (typeCase_ == TypeOneofCase.Subscribe) { + output.WriteRawTag(50); + output.WriteMessage(Subscribe); + } + if (typeCase_ == TypeOneofCase.OneOffQuery) { + output.WriteRawTag(58); + output.WriteMessage(OneOffQuery); + } + if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { + output.WriteRawTag(66); + output.WriteMessage(OneOffQueryResponse); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; if (typeCase_ == TypeOneofCase.FunctionCall) { @@ -288,6 +462,15 @@ public int CalculateSize() { if (typeCase_ == TypeOneofCase.IdentityToken) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(IdentityToken); } + if (typeCase_ == TypeOneofCase.Subscribe) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Subscribe); + } + if (typeCase_ == TypeOneofCase.OneOffQuery) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OneOffQuery); + } + if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OneOffQueryResponse); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -295,6 +478,7 @@ public int CalculateSize() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(Message other) { if (other == null) { return; @@ -330,13 +514,35 @@ public void MergeFrom(Message other) { } IdentityToken.MergeFrom(other.IdentityToken); break; + case TypeOneofCase.Subscribe: + if (Subscribe == null) { + Subscribe = new global::ClientApi.Subscribe(); + } + Subscribe.MergeFrom(other.Subscribe); + break; + case TypeOneofCase.OneOffQuery: + if (OneOffQuery == null) { + OneOffQuery = new global::ClientApi.OneOffQuery(); + } + OneOffQuery.MergeFrom(other.OneOffQuery); + break; + case TypeOneofCase.OneOffQueryResponse: + if (OneOffQueryResponse == null) { + OneOffQueryResponse = new global::ClientApi.OneOffQueryResponse(); + } + OneOffQueryResponse.MergeFrom(other.OneOffQueryResponse); + break; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -388,29 +594,162 @@ public void MergeFrom(pb::CodedInputStream input) { IdentityToken = subBuilder; break; } + case 50: { + global::ClientApi.Subscribe subBuilder = new global::ClientApi.Subscribe(); + if (typeCase_ == TypeOneofCase.Subscribe) { + subBuilder.MergeFrom(Subscribe); + } + input.ReadMessage(subBuilder); + Subscribe = subBuilder; + break; + } + case 58: { + global::ClientApi.OneOffQuery subBuilder = new global::ClientApi.OneOffQuery(); + if (typeCase_ == TypeOneofCase.OneOffQuery) { + subBuilder.MergeFrom(OneOffQuery); + } + input.ReadMessage(subBuilder); + OneOffQuery = subBuilder; + break; + } + case 66: { + global::ClientApi.OneOffQueryResponse subBuilder = new global::ClientApi.OneOffQueryResponse(); + if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { + subBuilder.MergeFrom(OneOffQueryResponse); + } + input.ReadMessage(subBuilder); + OneOffQueryResponse = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::ClientApi.FunctionCall subBuilder = new global::ClientApi.FunctionCall(); + if (typeCase_ == TypeOneofCase.FunctionCall) { + subBuilder.MergeFrom(FunctionCall); + } + input.ReadMessage(subBuilder); + FunctionCall = subBuilder; + break; + } + case 18: { + global::ClientApi.SubscriptionUpdate subBuilder = new global::ClientApi.SubscriptionUpdate(); + if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { + subBuilder.MergeFrom(SubscriptionUpdate); + } + input.ReadMessage(subBuilder); + SubscriptionUpdate = subBuilder; + break; + } + case 26: { + global::ClientApi.Event subBuilder = new global::ClientApi.Event(); + if (typeCase_ == TypeOneofCase.Event) { + subBuilder.MergeFrom(Event); + } + input.ReadMessage(subBuilder); + Event = subBuilder; + break; + } + case 34: { + global::ClientApi.TransactionUpdate subBuilder = new global::ClientApi.TransactionUpdate(); + if (typeCase_ == TypeOneofCase.TransactionUpdate) { + subBuilder.MergeFrom(TransactionUpdate); + } + input.ReadMessage(subBuilder); + TransactionUpdate = subBuilder; + break; + } + case 42: { + global::ClientApi.IdentityToken subBuilder = new global::ClientApi.IdentityToken(); + if (typeCase_ == TypeOneofCase.IdentityToken) { + subBuilder.MergeFrom(IdentityToken); + } + input.ReadMessage(subBuilder); + IdentityToken = subBuilder; + break; + } + case 50: { + global::ClientApi.Subscribe subBuilder = new global::ClientApi.Subscribe(); + if (typeCase_ == TypeOneofCase.Subscribe) { + subBuilder.MergeFrom(Subscribe); + } + input.ReadMessage(subBuilder); + Subscribe = subBuilder; + break; + } + case 58: { + global::ClientApi.OneOffQuery subBuilder = new global::ClientApi.OneOffQuery(); + if (typeCase_ == TypeOneofCase.OneOffQuery) { + subBuilder.MergeFrom(OneOffQuery); + } + input.ReadMessage(subBuilder); + OneOffQuery = subBuilder; + break; + } + case 66: { + global::ClientApi.OneOffQueryResponse subBuilder = new global::ClientApi.OneOffQueryResponse(); + if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { + subBuilder.MergeFrom(OneOffQueryResponse); + } + input.ReadMessage(subBuilder); + OneOffQueryResponse = subBuilder; + break; + } } } } + #endif } - public sealed partial class IdentityToken : pb::IMessage { + /// + //// Received by database from client to inform of user's identity, token and client address. + //// + //// The database will always send an `IdentityToken` message + //// as the first message for a new WebSocket connection. + //// If the client is re-connecting with existing credentials, + //// the message will include those credentials. + //// If the client connected anonymously, + //// the database will generate new credentials to identify it. + /// + public sealed partial class IdentityToken : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new IdentityToken()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public IdentityToken() { OnConstruction(); } @@ -418,13 +757,16 @@ public IdentityToken() { partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public IdentityToken(IdentityToken other) : this() { identity_ = other.identity_; token_ = other.token_; + address_ = other.address_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public IdentityToken Clone() { return new IdentityToken(this); } @@ -433,6 +775,7 @@ public IdentityToken Clone() { public const int IdentityFieldNumber = 1; private pb::ByteString identity_ = pb::ByteString.Empty; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public pb::ByteString Identity { get { return identity_; } set { @@ -444,6 +787,7 @@ public IdentityToken Clone() { public const int TokenFieldNumber = 2; private string token_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public string Token { get { return token_; } set { @@ -451,12 +795,26 @@ public string Token { } } + /// Field number for the "address" field. + public const int AddressFieldNumber = 3; + private pb::ByteString address_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pb::ByteString Address { + get { return address_; } + set { + address_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { return Equals(other as IdentityToken); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public bool Equals(IdentityToken other) { if (ReferenceEquals(other, null)) { return false; @@ -466,14 +824,17 @@ public bool Equals(IdentityToken other) { } if (Identity != other.Identity) return false; if (Token != other.Token) return false; + if (Address != other.Address) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; if (Identity.Length != 0) hash ^= Identity.GetHashCode(); if (Token.Length != 0) hash ^= Token.GetHashCode(); + if (Address.Length != 0) hash ^= Address.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -481,12 +842,17 @@ public override int GetHashCode() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Identity.Length != 0) { output.WriteRawTag(10); output.WriteBytes(Identity); @@ -495,12 +861,40 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(18); output.WriteString(Token); } + if (Address.Length != 0) { + output.WriteRawTag(26); + output.WriteBytes(Address); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Identity.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Identity); + } + if (Token.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Token); + } + if (Address.Length != 0) { + output.WriteRawTag(26); + output.WriteBytes(Address); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; if (Identity.Length != 0) { @@ -509,6 +903,9 @@ public int CalculateSize() { if (Token.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Token); } + if (Address.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Address); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -516,6 +913,7 @@ public int CalculateSize() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(IdentityToken other) { if (other == null) { return; @@ -526,11 +924,18 @@ public void MergeFrom(IdentityToken other) { if (other.Token.Length != 0) { Token = other.Token; } + if (other.Address.Length != 0) { + Address = other.Address; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -545,33 +950,80 @@ public void MergeFrom(pb::CodedInputStream input) { Token = input.ReadString(); break; } + case 26: { + Address = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Identity = input.ReadBytes(); + break; + } + case 18: { + Token = input.ReadString(); + break; + } + case 26: { + Address = input.ReadBytes(); + break; + } } } } + #endif } /// - /// TODO: Evaluate if it makes sense for this to also include the - /// identity and name of the module this is calling + //// Sent by client to database to request a reducer runs. + //// + //// - `reducer` is the string name of a reducer to run. + //// + //// - `argBytes` is the arguments to the reducer, encoded as BSATN. + //// + //// SpacetimeDB models reducers as taking a single `AlgebraicValue` as an argument, which + //// generally will be a `ProductValue` containing all of the args (except the + //// `ReducerContext`, which is injected by the host, not provided in this API). /// - public sealed partial class FunctionCall : pb::IMessage { + public sealed partial class FunctionCall : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FunctionCall()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public FunctionCall() { OnConstruction(); } @@ -579,6 +1031,7 @@ public FunctionCall() { partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public FunctionCall(FunctionCall other) : this() { reducer_ = other.reducer_; argBytes_ = other.argBytes_; @@ -586,6 +1039,7 @@ public FunctionCall(FunctionCall other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public FunctionCall Clone() { return new FunctionCall(this); } @@ -597,6 +1051,7 @@ public FunctionCall Clone() { /// TODO: Maybe this should be replaced with an int identifier for performance? ///
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public string Reducer { get { return reducer_; } set { @@ -608,6 +1063,7 @@ public string Reducer { public const int ArgBytesFieldNumber = 2; private pb::ByteString argBytes_ = pb::ByteString.Empty; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public pb::ByteString ArgBytes { get { return argBytes_; } set { @@ -616,11 +1072,13 @@ public string Reducer { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { return Equals(other as FunctionCall); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public bool Equals(FunctionCall other) { if (ReferenceEquals(other, null)) { return false; @@ -634,6 +1092,7 @@ public bool Equals(FunctionCall other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; if (Reducer.Length != 0) hash ^= Reducer.GetHashCode(); @@ -645,12 +1104,17 @@ public override int GetHashCode() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Reducer.Length != 0) { output.WriteRawTag(10); output.WriteString(Reducer); @@ -662,9 +1126,29 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Reducer.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Reducer); + } + if (ArgBytes.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(ArgBytes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; if (Reducer.Length != 0) { @@ -680,6 +1164,7 @@ public int CalculateSize() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(FunctionCall other) { if (other == null) { return; @@ -694,7 +1179,11 @@ public void MergeFrom(FunctionCall other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -711,55 +1200,329 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Reducer = input.ReadString(); + break; + } + case 18: { + ArgBytes = input.ReadBytes(); + break; + } + } + } } + #endif } - public sealed partial class Event : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Event()); + /// + //// Sent by client to database to register a set of queries, about which the client will + //// receive `TransactionUpdate`s. + //// + //// `query_strings` is a sequence of strings, each of which is a SQL query. + //// + //// After issuing a `Subscribe` message, the client will receive a single + //// `SubscriptionUpdate` message containing every current row of every table which matches + //// the subscribed queries. Then, after each reducer run which updates one or more + //// subscribed rows, the client will receive a `TransactionUpdate` containing the updates. + //// + //// A `Subscribe` message sets or replaces the entire set of queries to which the client + //// is subscribed. If the client is previously subscribed to some set of queries `A`, and + //// then sends a `Subscribe` message to subscribe to a set `B`, afterwards, the client + //// will be subscribed to `B` but not `A`. In this case, the client will receive a + //// `SubscriptionUpdate` containing every existing row that matches `B`, even if some were + //// already in `A`. + /// + public sealed partial class Subscribe : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Subscribe()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Event() { + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Subscribe() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Event(Event other) : this() { - timestamp_ = other.timestamp_; - callerIdentity_ = other.callerIdentity_; - functionCall_ = other.functionCall_ != null ? other.functionCall_.Clone() : null; - status_ = other.status_; - message_ = other.message_; - energyQuantaUsed_ = other.energyQuantaUsed_; - hostExecutionDurationMicros_ = other.hostExecutionDurationMicros_; + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Subscribe(Subscribe other) : this() { + queryStrings_ = other.queryStrings_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Event Clone() { - return new Event(this); + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Subscribe Clone() { + return new Subscribe(this); } - /// Field number for the "timestamp" field. - public const int TimestampFieldNumber = 1; - private ulong timestamp_; + /// Field number for the "query_strings" field. + public const int QueryStringsFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_queryStrings_codec + = pb::FieldCodec.ForString(10); + private readonly pbc::RepeatedField queryStrings_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ulong Timestamp { + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField QueryStrings { + get { return queryStrings_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Subscribe); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Subscribe other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!queryStrings_.Equals(other.queryStrings_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= queryStrings_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + queryStrings_.WriteTo(output, _repeated_queryStrings_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + queryStrings_.WriteTo(ref output, _repeated_queryStrings_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += queryStrings_.CalculateSize(_repeated_queryStrings_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Subscribe other) { + if (other == null) { + return; + } + queryStrings_.Add(other.queryStrings_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + queryStrings_.AddEntriesFrom(input, _repeated_queryStrings_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + queryStrings_.AddEntriesFrom(ref input, _repeated_queryStrings_codec); + break; + } + } + } + } + #endif + + } + + /// + //// Part of a `TransactionUpdate` received by client from database upon a reducer run. + //// + //// - `timestamp` is the time when the reducer started, + //// as microseconds since the Unix epoch. + //// + //// - `callerIdentity` is the identity of the user who requested the reducer run. + //// For event-driven and scheduled reducers, + //// it is the identity of the database owner. + //// + //// - `functionCall` contains the name of the reducer which ran and the arguments it + //// received. + //// + //// - `status` of `committed` means that the reducer ran successfully and its changes were + //// committed to the database. The rows altered in the database + //// will be recorded in the parent `TransactionUpdate`'s + //// `SubscriptionUpdate`. + //// + //// - `status` of `failed` means that the reducer panicked, and any changes it attempted to + //// make were rolled back. + //// + //// - `status` of `out_of_energy` means that the reducer was interrupted + //// due to insufficient energy/funds, + //// and any changes it attempted to make were rolled back. + //// + //// - `message` is the error message with which the reducer failed. + //// For `committed` or `out_of_energy` statuses, + //// it is the empty string. + //// + //// - `energy_quanta_used` and `host_execution_duration_micros` seem self-explanatory; + //// they describe the amount of energy credits consumed by running the reducer, + //// and how long it took to run. + //// + //// - `callerAddress` is the 16-byte address of the user who requested the reducer run. + //// The all-zeros address is a sentinel which denotes no address. + //// `init` and `update` reducers will have a `callerAddress` + //// if and only if one was provided to the `publish` HTTP endpoint. + //// Scheduled reducers will never have a `callerAddress`. + //// Reducers invoked by HTTP will have a `callerAddress` + //// if and only if one was provided to the `call` HTTP endpoint. + //// Reducers invoked by WebSocket will always have a `callerAddress`. + /// + public sealed partial class Event : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Event()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Event() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Event(Event other) : this() { + timestamp_ = other.timestamp_; + callerIdentity_ = other.callerIdentity_; + functionCall_ = other.functionCall_ != null ? other.functionCall_.Clone() : null; + status_ = other.status_; + message_ = other.message_; + energyQuantaUsed_ = other.energyQuantaUsed_; + hostExecutionDurationMicros_ = other.hostExecutionDurationMicros_; + callerAddress_ = other.callerAddress_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Event Clone() { + return new Event(this); + } + + /// Field number for the "timestamp" field. + public const int TimestampFieldNumber = 1; + private ulong timestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong Timestamp { get { return timestamp_; } set { timestamp_ = value; @@ -770,6 +1533,7 @@ public ulong Timestamp { public const int CallerIdentityFieldNumber = 2; private pb::ByteString callerIdentity_ = pb::ByteString.Empty; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public pb::ByteString CallerIdentity { get { return callerIdentity_; } set { @@ -781,6 +1545,7 @@ public ulong Timestamp { public const int FunctionCallFieldNumber = 3; private global::ClientApi.FunctionCall functionCall_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.FunctionCall FunctionCall { get { return functionCall_; } set { @@ -796,6 +1561,7 @@ public ulong Timestamp { /// since success doesn't have a message ///
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.Event.Types.Status Status { get { return status_; } set { @@ -807,6 +1573,7 @@ public ulong Timestamp { public const int MessageFieldNumber = 5; private string message_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public string Message { get { return message_; } set { @@ -818,6 +1585,7 @@ public string Message { public const int EnergyQuantaUsedFieldNumber = 6; private long energyQuantaUsed_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public long EnergyQuantaUsed { get { return energyQuantaUsed_; } set { @@ -829,6 +1597,7 @@ public long EnergyQuantaUsed { public const int HostExecutionDurationMicrosFieldNumber = 7; private ulong hostExecutionDurationMicros_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public ulong HostExecutionDurationMicros { get { return hostExecutionDurationMicros_; } set { @@ -836,12 +1605,26 @@ public ulong HostExecutionDurationMicros { } } + /// Field number for the "callerAddress" field. + public const int CallerAddressFieldNumber = 8; + private pb::ByteString callerAddress_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pb::ByteString CallerAddress { + get { return callerAddress_; } + set { + callerAddress_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { return Equals(other as Event); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public bool Equals(Event other) { if (ReferenceEquals(other, null)) { return false; @@ -856,10 +1639,12 @@ public bool Equals(Event other) { if (Message != other.Message) return false; if (EnergyQuantaUsed != other.EnergyQuantaUsed) return false; if (HostExecutionDurationMicros != other.HostExecutionDurationMicros) return false; + if (CallerAddress != other.CallerAddress) return false; return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; if (Timestamp != 0UL) hash ^= Timestamp.GetHashCode(); @@ -869,6 +1654,7 @@ public override int GetHashCode() { if (Message.Length != 0) hash ^= Message.GetHashCode(); if (EnergyQuantaUsed != 0L) hash ^= EnergyQuantaUsed.GetHashCode(); if (HostExecutionDurationMicros != 0UL) hash ^= HostExecutionDurationMicros.GetHashCode(); + if (CallerAddress.Length != 0) hash ^= CallerAddress.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -876,12 +1662,17 @@ public override int GetHashCode() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Timestamp != 0UL) { output.WriteRawTag(8); output.WriteUInt64(Timestamp); @@ -910,12 +1701,60 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(56); output.WriteUInt64(HostExecutionDurationMicros); } + if (CallerAddress.Length != 0) { + output.WriteRawTag(66); + output.WriteBytes(CallerAddress); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Timestamp != 0UL) { + output.WriteRawTag(8); + output.WriteUInt64(Timestamp); + } + if (CallerIdentity.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(CallerIdentity); + } + if (functionCall_ != null) { + output.WriteRawTag(26); + output.WriteMessage(FunctionCall); + } + if (Status != global::ClientApi.Event.Types.Status.Committed) { + output.WriteRawTag(32); + output.WriteEnum((int) Status); + } + if (Message.Length != 0) { + output.WriteRawTag(42); + output.WriteString(Message); + } + if (EnergyQuantaUsed != 0L) { + output.WriteRawTag(48); + output.WriteInt64(EnergyQuantaUsed); + } + if (HostExecutionDurationMicros != 0UL) { + output.WriteRawTag(56); + output.WriteUInt64(HostExecutionDurationMicros); + } + if (CallerAddress.Length != 0) { + output.WriteRawTag(66); + output.WriteBytes(CallerAddress); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; if (Timestamp != 0UL) { @@ -939,6 +1778,9 @@ public int CalculateSize() { if (HostExecutionDurationMicros != 0UL) { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(HostExecutionDurationMicros); } + if (CallerAddress.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(CallerAddress); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -946,6 +1788,7 @@ public int CalculateSize() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(Event other) { if (other == null) { return; @@ -974,11 +1817,18 @@ public void MergeFrom(Event other) { if (other.HostExecutionDurationMicros != 0UL) { HostExecutionDurationMicros = other.HostExecutionDurationMicros; } + if (other.CallerAddress.Length != 0) { + CallerAddress = other.CallerAddress; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1016,13 +1866,69 @@ public void MergeFrom(pb::CodedInputStream input) { HostExecutionDurationMicros = input.ReadUInt64(); break; } + case 66: { + CallerAddress = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Timestamp = input.ReadUInt64(); + break; + } + case 18: { + CallerIdentity = input.ReadBytes(); + break; + } + case 26: { + if (functionCall_ == null) { + FunctionCall = new global::ClientApi.FunctionCall(); + } + input.ReadMessage(FunctionCall); + break; + } + case 32: { + Status = (global::ClientApi.Event.Types.Status) input.ReadEnum(); + break; + } + case 42: { + Message = input.ReadString(); + break; + } + case 48: { + EnergyQuantaUsed = input.ReadInt64(); + break; + } + case 56: { + HostExecutionDurationMicros = input.ReadUInt64(); + break; + } + case 66: { + CallerAddress = input.ReadBytes(); + break; + } } } } + #endif #region Nested types /// Container for nested types declared in the Event message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static partial class Types { public enum Status { [pbr::OriginalName("committed")] Committed = 0, @@ -1036,25 +1942,38 @@ public enum Status { } /// - /// TODO: Maybe call this StateUpdate if it's implied to be a subscription update + //// Part of a `TransactionUpdate` received by client from database when subscribed rows in + //// a table are altered, or received alone after a `Subscription` to initialize the + //// client's mirror of the database. + //// + //// A single `SubscriptionUpdate` may contain `TableUpdate` messages for multiple + //// tables. /// - public sealed partial class SubscriptionUpdate : pb::IMessage { + public sealed partial class SubscriptionUpdate : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubscriptionUpdate()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[4]; } + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public SubscriptionUpdate() { OnConstruction(); } @@ -1062,12 +1981,14 @@ public SubscriptionUpdate() { partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public SubscriptionUpdate(SubscriptionUpdate other) : this() { tableUpdates_ = other.tableUpdates_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public SubscriptionUpdate Clone() { return new SubscriptionUpdate(this); } @@ -1078,16 +1999,19 @@ public SubscriptionUpdate Clone() { = pb::FieldCodec.ForMessage(10, global::ClientApi.TableUpdate.Parser); private readonly pbc::RepeatedField tableUpdates_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public pbc::RepeatedField TableUpdates { get { return tableUpdates_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { return Equals(other as SubscriptionUpdate); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public bool Equals(SubscriptionUpdate other) { if (ReferenceEquals(other, null)) { return false; @@ -1100,6 +2024,7 @@ public bool Equals(SubscriptionUpdate other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; hash ^= tableUpdates_.GetHashCode(); @@ -1110,19 +2035,37 @@ public override int GetHashCode() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else tableUpdates_.WriteTo(output, _repeated_tableUpdates_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + tableUpdates_.WriteTo(ref output, _repeated_tableUpdates_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; size += tableUpdates_.CalculateSize(_repeated_tableUpdates_codec); @@ -1133,6 +2076,7 @@ public int CalculateSize() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(SubscriptionUpdate other) { if (other == null) { return; @@ -1142,7 +2086,11 @@ public void MergeFrom(SubscriptionUpdate other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1155,27 +2103,65 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + tableUpdates_.AddEntriesFrom(ref input, _repeated_tableUpdates_codec); + break; + } + } + } } + #endif } - public sealed partial class TableUpdate : pb::IMessage { + /// + //// Part of a `SubscriptionUpdate` received by client from database for alterations to a + //// single table. + //// + //// `tableId` and `tableName` identify the table. Clients should use the `tableName`, as + //// it is a stable part of a module's API, whereas `tableId` may + //// or may not change between runs. + //// + //// `tableRowOperations` are actual modified rows. + /// + public sealed partial class TableUpdate : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TableUpdate()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[5]; } + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[6]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TableUpdate() { OnConstruction(); } @@ -1183,6 +2169,7 @@ public TableUpdate() { partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TableUpdate(TableUpdate other) : this() { tableId_ = other.tableId_; tableName_ = other.tableName_; @@ -1191,6 +2178,7 @@ public TableUpdate(TableUpdate other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TableUpdate Clone() { return new TableUpdate(this); } @@ -1199,6 +2187,7 @@ public TableUpdate Clone() { public const int TableIdFieldNumber = 1; private uint tableId_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public uint TableId { get { return tableId_; } set { @@ -1210,6 +2199,7 @@ public uint TableId { public const int TableNameFieldNumber = 2; private string tableName_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public string TableName { get { return tableName_; } set { @@ -1223,16 +2213,19 @@ public string TableName { = pb::FieldCodec.ForMessage(26, global::ClientApi.TableRowOperation.Parser); private readonly pbc::RepeatedField tableRowOperations_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public pbc::RepeatedField TableRowOperations { get { return tableRowOperations_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { return Equals(other as TableUpdate); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public bool Equals(TableUpdate other) { if (ReferenceEquals(other, null)) { return false; @@ -1247,6 +2240,7 @@ public bool Equals(TableUpdate other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; if (TableId != 0) hash ^= TableId.GetHashCode(); @@ -1259,12 +2253,17 @@ public override int GetHashCode() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (TableId != 0) { output.WriteRawTag(8); output.WriteUInt32(TableId); @@ -1277,25 +2276,47 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (TableId != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TableId); + output.WriteRawTag(8); + output.WriteUInt32(TableId); } if (TableName.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(TableName); + output.WriteRawTag(18); + output.WriteString(TableName); } - size += tableRowOperations_.CalculateSize(_repeated_tableRowOperations_codec); + tableRowOperations_.WriteTo(ref output, _repeated_tableRowOperations_codec); if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); + _unknownFields.WriteTo(ref output); } - return size; } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (TableId != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TableId); + } + if (TableName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(TableName); + } + size += tableRowOperations_.CalculateSize(_repeated_tableRowOperations_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(TableUpdate other) { if (other == null) { return; @@ -1311,7 +2332,11 @@ public void MergeFrom(TableUpdate other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1332,27 +2357,81 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + TableId = input.ReadUInt32(); + break; + } + case 18: { + TableName = input.ReadString(); + break; + } + case 26: { + tableRowOperations_.AddEntriesFrom(ref input, _repeated_tableRowOperations_codec); + break; + } + } + } } + #endif } - public sealed partial class TableRowOperation : pb::IMessage { + /// + //// Part of a `TableUpdate` received by client from database for alteration to a single + //// row of a table. + //// + //// The table being altered is identified by the parent `TableUpdate`. + //// + //// - `op` of `DELETE` means that the row in question has been removed and is no longer + //// resident in the table. + //// + //// - `op` of `INSERT` means that the row in question has been either newly inserted or + //// updated, and is resident in the table. + //// + //// - `row_pk` is a hash of the row computed by the database. As of 2023-06-13, even for + //// tables with a `#[primarykey]` annotation on one column, the `row_pk` is not + //// that primary key. + //// + //// - `row` is the row itself, encoded as BSATN. + /// + public sealed partial class TableRowOperation : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TableRowOperation()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[6]; } + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[7]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TableRowOperation() { OnConstruction(); } @@ -1360,6 +2439,7 @@ public TableRowOperation() { partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TableRowOperation(TableRowOperation other) : this() { op_ = other.op_; rowPk_ = other.rowPk_; @@ -1368,6 +2448,7 @@ public TableRowOperation(TableRowOperation other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TableRowOperation Clone() { return new TableRowOperation(this); } @@ -1376,6 +2457,7 @@ public TableRowOperation Clone() { public const int OpFieldNumber = 1; private global::ClientApi.TableRowOperation.Types.OperationType op_ = global::ClientApi.TableRowOperation.Types.OperationType.Delete; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.TableRowOperation.Types.OperationType Op { get { return op_; } set { @@ -1387,6 +2469,7 @@ public TableRowOperation Clone() { public const int RowPkFieldNumber = 2; private pb::ByteString rowPk_ = pb::ByteString.Empty; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public pb::ByteString RowPk { get { return rowPk_; } set { @@ -1398,6 +2481,7 @@ public TableRowOperation Clone() { public const int RowFieldNumber = 3; private pb::ByteString row_ = pb::ByteString.Empty; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public pb::ByteString Row { get { return row_; } set { @@ -1406,11 +2490,13 @@ public TableRowOperation Clone() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { return Equals(other as TableRowOperation); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public bool Equals(TableRowOperation other) { if (ReferenceEquals(other, null)) { return false; @@ -1425,6 +2511,7 @@ public bool Equals(TableRowOperation other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) hash ^= Op.GetHashCode(); @@ -1437,12 +2524,17 @@ public override int GetHashCode() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { output.WriteRawTag(8); output.WriteEnum((int) Op); @@ -1458,9 +2550,33 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { + output.WriteRawTag(8); + output.WriteEnum((int) Op); + } + if (RowPk.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(RowPk); + } + if (Row.Length != 0) { + output.WriteRawTag(26); + output.WriteBytes(Row); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { @@ -1479,6 +2595,7 @@ public int CalculateSize() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(TableRowOperation other) { if (other == null) { return; @@ -1496,7 +2613,11 @@ public void MergeFrom(TableRowOperation other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1517,11 +2638,40 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Op = (global::ClientApi.TableRowOperation.Types.OperationType) input.ReadEnum(); + break; + } + case 18: { + RowPk = input.ReadBytes(); + break; + } + case 26: { + Row = input.ReadBytes(); + break; + } + } + } } + #endif #region Nested types /// Container for nested types declared in the TableRowOperation message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static partial class Types { public enum OperationType { [pbr::OriginalName("DELETE")] Delete = 0, @@ -1533,23 +2683,42 @@ public enum OperationType { } - public sealed partial class TransactionUpdate : pb::IMessage { + /// + //// Received by client from database upon a reducer run. + //// + //// Clients receive `TransactionUpdate`s only for reducers + //// which update at least one of their subscribed rows, + //// or for their own `failed` or `out_of_energy` reducer invocations. + //// + //// - `event` contains information about the reducer. + //// + //// - `subscriptionUpdate` contains changes to subscribed rows. + /// + public sealed partial class TransactionUpdate : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TransactionUpdate()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[7]; } + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[8]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] pbr::MessageDescriptor pb::IMessage.Descriptor { get { return Descriptor; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TransactionUpdate() { OnConstruction(); } @@ -1557,6 +2726,7 @@ public TransactionUpdate() { partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TransactionUpdate(TransactionUpdate other) : this() { event_ = other.event_ != null ? other.event_.Clone() : null; subscriptionUpdate_ = other.subscriptionUpdate_ != null ? other.subscriptionUpdate_.Clone() : null; @@ -1564,6 +2734,7 @@ public TransactionUpdate(TransactionUpdate other) : this() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TransactionUpdate Clone() { return new TransactionUpdate(this); } @@ -1572,6 +2743,7 @@ public TransactionUpdate Clone() { public const int EventFieldNumber = 1; private global::ClientApi.Event event_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.Event Event { get { return event_; } set { @@ -1583,6 +2755,7 @@ public TransactionUpdate Clone() { public const int SubscriptionUpdateFieldNumber = 2; private global::ClientApi.SubscriptionUpdate subscriptionUpdate_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public global::ClientApi.SubscriptionUpdate SubscriptionUpdate { get { return subscriptionUpdate_; } set { @@ -1591,11 +2764,13 @@ public TransactionUpdate Clone() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { return Equals(other as TransactionUpdate); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public bool Equals(TransactionUpdate other) { if (ReferenceEquals(other, null)) { return false; @@ -1609,6 +2784,7 @@ public bool Equals(TransactionUpdate other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; if (event_ != null) hash ^= Event.GetHashCode(); @@ -1620,12 +2796,17 @@ public override int GetHashCode() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override string ToString() { return pb::JsonFormatter.ToDiagnosticString(this); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (event_ != null) { output.WriteRawTag(10); output.WriteMessage(Event); @@ -1637,9 +2818,29 @@ public void WriteTo(pb::CodedOutputStream output) { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (event_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Event); + } + if (subscriptionUpdate_ != null) { + output.WriteRawTag(18); + output.WriteMessage(SubscriptionUpdate); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; if (event_ != null) { @@ -1655,6 +2856,7 @@ public int CalculateSize() { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(TransactionUpdate other) { if (other == null) { return; @@ -1675,7 +2877,11 @@ public void MergeFrom(TransactionUpdate other) { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { @@ -1698,7 +2904,750 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (event_ == null) { + Event = new global::ClientApi.Event(); + } + input.ReadMessage(Event); + break; + } + case 18: { + if (subscriptionUpdate_ == null) { + SubscriptionUpdate = new global::ClientApi.SubscriptionUpdate(); + } + input.ReadMessage(SubscriptionUpdate); + break; + } + } + } + } + #endif + + } + + /// + //// A one-off query submission. + //// + //// Query should be a "SELECT * FROM Table WHERE ...". Other types of queries will be rejected. + //// Multiple such semicolon-delimited queries are allowed. + //// + //// One-off queries are identified by a client-generated messageID. + //// To avoid data leaks, the server will NOT cache responses to messages based on UUID! + //// It also will not check for duplicate IDs. They are just a way to match responses to messages. + /// + public sealed partial class OneOffQuery : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneOffQuery()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffQuery() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffQuery(OneOffQuery other) : this() { + messageId_ = other.messageId_; + queryString_ = other.queryString_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffQuery Clone() { + return new OneOffQuery(this); + } + + /// Field number for the "messageId" field. + public const int MessageIdFieldNumber = 1; + private pb::ByteString messageId_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pb::ByteString MessageId { + get { return messageId_; } + set { + messageId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "queryString" field. + public const int QueryStringFieldNumber = 2; + private string queryString_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string QueryString { + get { return queryString_; } + set { + queryString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as OneOffQuery); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(OneOffQuery other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (MessageId != other.MessageId) return false; + if (QueryString != other.QueryString) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (MessageId.Length != 0) hash ^= MessageId.GetHashCode(); + if (QueryString.Length != 0) hash ^= QueryString.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (MessageId.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(MessageId); + } + if (QueryString.Length != 0) { + output.WriteRawTag(18); + output.WriteString(QueryString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (MessageId.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(MessageId); + } + if (QueryString.Length != 0) { + output.WriteRawTag(18); + output.WriteString(QueryString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (MessageId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(MessageId); + } + if (QueryString.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(QueryString); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(OneOffQuery other) { + if (other == null) { + return; + } + if (other.MessageId.Length != 0) { + MessageId = other.MessageId; + } + if (other.QueryString.Length != 0) { + QueryString = other.QueryString; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + MessageId = input.ReadBytes(); + break; + } + case 18: { + QueryString = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + MessageId = input.ReadBytes(); + break; + } + case 18: { + QueryString = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + //// A one-off query response. + //// Will contain either one error or multiple response rows. + //// At most one of these messages will be sent in reply to any query. + //// + //// The messageId will be identical to the one sent in the original query. + /// + public sealed partial class OneOffQueryResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneOffQueryResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffQueryResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffQueryResponse(OneOffQueryResponse other) : this() { + messageId_ = other.messageId_; + error_ = other.error_; + tables_ = other.tables_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffQueryResponse Clone() { + return new OneOffQueryResponse(this); + } + + /// Field number for the "messageId" field. + public const int MessageIdFieldNumber = 1; + private pb::ByteString messageId_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pb::ByteString MessageId { + get { return messageId_; } + set { + messageId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "error" field. + public const int ErrorFieldNumber = 2; + private string error_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Error { + get { return error_; } + set { + error_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "tables" field. + public const int TablesFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_tables_codec + = pb::FieldCodec.ForMessage(26, global::ClientApi.OneOffTable.Parser); + private readonly pbc::RepeatedField tables_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Tables { + get { return tables_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as OneOffQueryResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(OneOffQueryResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (MessageId != other.MessageId) return false; + if (Error != other.Error) return false; + if(!tables_.Equals(other.tables_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (MessageId.Length != 0) hash ^= MessageId.GetHashCode(); + if (Error.Length != 0) hash ^= Error.GetHashCode(); + hash ^= tables_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (MessageId.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(MessageId); + } + if (Error.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Error); + } + tables_.WriteTo(output, _repeated_tables_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (MessageId.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(MessageId); + } + if (Error.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Error); + } + tables_.WriteTo(ref output, _repeated_tables_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (MessageId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(MessageId); + } + if (Error.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Error); + } + size += tables_.CalculateSize(_repeated_tables_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(OneOffQueryResponse other) { + if (other == null) { + return; + } + if (other.MessageId.Length != 0) { + MessageId = other.MessageId; + } + if (other.Error.Length != 0) { + Error = other.Error; + } + tables_.Add(other.tables_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + MessageId = input.ReadBytes(); + break; + } + case 18: { + Error = input.ReadString(); + break; + } + case 26: { + tables_.AddEntriesFrom(input, _repeated_tables_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + MessageId = input.ReadBytes(); + break; + } + case 18: { + Error = input.ReadString(); + break; + } + case 26: { + tables_.AddEntriesFrom(ref input, _repeated_tables_codec); + break; + } + } + } + } + #endif + + } + + /// + //// A table included as part of a one-off query. + /// + public sealed partial class OneOffTable : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneOffTable()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffTable() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffTable(OneOffTable other) : this() { + tableName_ = other.tableName_; + row_ = other.row_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneOffTable Clone() { + return new OneOffTable(this); + } + + /// Field number for the "tableName" field. + public const int TableNameFieldNumber = 2; + private string tableName_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string TableName { + get { return tableName_; } + set { + tableName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "row" field. + public const int RowFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_row_codec + = pb::FieldCodec.ForBytes(34); + private readonly pbc::RepeatedField row_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Row { + get { return row_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as OneOffTable); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(OneOffTable other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (TableName != other.TableName) return false; + if(!row_.Equals(other.row_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (TableName.Length != 0) hash ^= TableName.GetHashCode(); + hash ^= row_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (TableName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(TableName); + } + row_.WriteTo(output, _repeated_row_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (TableName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(TableName); + } + row_.WriteTo(ref output, _repeated_row_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (TableName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(TableName); + } + size += row_.CalculateSize(_repeated_row_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(OneOffTable other) { + if (other == null) { + return; + } + if (other.TableName.Length != 0) { + TableName = other.TableName; + } + row_.Add(other.row_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 18: { + TableName = input.ReadString(); + break; + } + case 34: { + row_.AddEntriesFrom(input, _repeated_row_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 18: { + TableName = input.ReadString(); + break; + } + case 34: { + row_.AddEntriesFrom(ref input, _repeated_row_codec); + break; + } + } + } } + #endif } diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 3f0343bc0f3..ca06ded6952 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -134,6 +134,18 @@ public void SetDecodedValue(byte[] pk, AlgebraicValue value, out object obj) } } + /// + /// Decodes the given AlgebraicValue into the out parameter `obj`. + /// Does NOT cache the resulting value! This should only be used with rows + /// that don't participate in the usual client cache lifecycle, i.e. OneOffQuery. + /// + /// The AlgebraicValue to decode. + /// The domain object for `value` + public void SetAndForgetDecodedValue(AlgebraicValue value, out object obj) + { + obj = decoderFunc(value); + } + /// /// Inserts the value into the table. There can be no existing value with the provided pk. /// diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index b9dfd94205b..df95f104150 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Text; using System.Threading; +using System.Threading.Channels; using System.Threading.Tasks; using ClientApi; using Newtonsoft.Json; @@ -77,22 +78,31 @@ public struct DbOp /// public event Action onSubscriptionApplied; + /// + /// Invoked when a reducer is returned with an error and has no client-side handler. + /// + public event Action onUnhandledReducerError; + /// /// Called when we receive an identity from the server /// - public event Action onIdentityReceived; + public event Action onIdentityReceived; /// /// Invoked when an event message is received or at the end of a transaction update. /// public event Action onEvent; + public Address clientAddress { get; private set; } + private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; public static ClientCache clientDB; public static Dictionary> reducerEventCache = new Dictionary>(); public static Dictionary> deserializeEventCache = new Dictionary>(); + private static Dictionary> waitingOneOffQueries = new Dictionary>(); + private bool isClosing; private Thread messageProcessThread; @@ -148,6 +158,8 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) instance = this; + clientAddress = Address.Random(); + logger = loggerToUse; var options = new SpacetimeDB.ConnectOptions @@ -392,6 +404,21 @@ void ProcessMessages() break; case ClientApi.Message.TypeOneofCase.Event: break; + case ClientApi.Message.TypeOneofCase.OneOffQuery: + break; + case ClientApi.Message.TypeOneofCase.OneOffQueryResponse: + /// This case does NOT produce a list of DBOps, because it should not modify the client cache state! + var resp = message.OneOffQueryResponse; + Guid messageId = new Guid(resp.MessageId.Span); + + if (!waitingOneOffQueries.ContainsKey(messageId)) + { + logger.LogError("Response to unknown one-off-query: " + messageId); + break; + } + waitingOneOffQueries[messageId].Writer.TryWrite(resp); + waitingOneOffQueries.Remove(messageId); + break; } if (message.TypeCase == Message.TypeOneofCase.SubscriptionUpdate) @@ -447,19 +474,25 @@ public void Close() /// /// Connect to a remote spacetime instance. /// - /// The host or IP address and the port to connect to. Example: spacetime.spacetimedb.net:3000 + /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - /// Should websocket use SSL - public void Connect(string token, string host, string addressOrName, bool sslEnabled = true) + public void Connect(string token, string uri, string addressOrName) { isClosing = false; - logger.Log($"SpacetimeDBClient: Connecting to {host} {addressOrName}"); + uri = uri.Replace("http://", "ws://"); + uri = uri.Replace("https://", "wss://"); + if (!uri.StartsWith("ws://") && !uri.StartsWith("wss://")) + { + uri = $"ws://{uri}"; + } + + logger.Log($"SpacetimeDBClient: Connecting to {uri} {addressOrName}"); Task.Run(async () => { try { - await webSocket.Connect(token, host, addressOrName, sslEnabled); + await webSocket.Connect(token, uri, addressOrName, clientAddress); } catch (Exception e) { @@ -666,10 +699,15 @@ private void OnMessageProcessComplete(Message message, IList dbOps) case Message.TypeOneofCase.TransactionUpdate: onEvent?.Invoke(message.TransactionUpdate.Event); + bool reducerFound = false; var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; if (reducerEventCache.TryGetValue(functionName, out var value)) { - value.Invoke(message.TransactionUpdate.Event); + reducerFound = value.Invoke(message.TransactionUpdate.Event); + } + if (!reducerFound && message.TransactionUpdate.Event.Status == ClientApi.Event.Types.Status.Failed) + { + onUnhandledReducerError?.Invoke(message.TransactionUpdate.Event.FunctionCall.CallInfo); } break; @@ -687,7 +725,7 @@ private void OnMessageProcessComplete(Message message, IList dbOps) break; case Message.TypeOneofCase.IdentityToken: - onIdentityReceived?.Invoke(message.IdentityToken.Token, Identity.From(message.IdentityToken.Identity.ToByteArray())); + onIdentityReceived?.Invoke(message.IdentityToken.Token, Identity.From(message.IdentityToken.Identity.ToByteArray()), (Address)Address.From(message.IdentityToken.Address.ToByteArray())); break; case Message.TypeOneofCase.Event: onEvent?.Invoke(message.Event); @@ -715,9 +753,75 @@ public void Subscribe(List queries) return; } var json = JsonConvert.SerializeObject(queries); + // should we use UTF8 here? ASCII is fragile. webSocket.Send(Encoding.ASCII.GetBytes("{ \"subscribe\": { \"query_strings\": " + json + " }}")); } + /// Usage: SpacetimeDBClient.instance.OneOffQuery("WHERE sender = \"bob\""); + public async Task OneOffQuery(string query) where T : IDatabaseTable + { + Guid messageId = Guid.NewGuid(); + Type type = typeof(T); + Channel resultChannel = Channel.CreateBounded(1); + waitingOneOffQueries[messageId] = resultChannel; + + // unsanitized here, but writes will be prevented serverside. + // the best they can do is send multiple selects, which will just result in them getting no data back. + string queryString = "SELECT * FROM " + type.Name + " " + query; + + // see: SpacetimeDB\crates\core\src\client\message_handlers.rs, enum Message<'a> + var serializedQuery = "{ \"one_off_query\": { \"message_id\": \"" + System.Convert.ToBase64String(messageId.ToByteArray()) + + "\", \"query_string\": " + JsonConvert.SerializeObject(queryString) + " } }"; + webSocket.Send(Encoding.UTF8.GetBytes(serializedQuery)); + + // Suspend for an arbitrary amount of time + var result = await resultChannel.Reader.ReadAsync(); + + T[] LogAndThrow(string error) + { + error = "While processing one-off-query `" + queryString + "`, ID " + messageId + ": " + error; + logger.LogError(error); + throw new Exception(error); + } + + // The server got back to us + if (result.Error != null && result.Error != "") + { + return LogAndThrow("Server error: " + result.Error); + } + + if (result.Tables.Count != 1) + { + return LogAndThrow("Expected a single table, but got " + result.Tables.Count); + } + + var resultTable = result.Tables[0]; + var cacheTable = clientDB.GetTable(resultTable.TableName); + + if (cacheTable.ClientTableType != type) + { + return LogAndThrow("Mismatched result type, expected " + type + " but got " + resultTable.TableName); + } + + T[] results = (T[])Array.CreateInstance(type, resultTable.Row.Count); + using var stream = new MemoryStream(); + using var reader = new BinaryReader(stream); + for (int i = 0; i < results.Length; i++) + { + var rowValue = resultTable.Row[i].ToByteArray(); + stream.Position = 0; + stream.Write(rowValue, 0, rowValue.Length); + stream.Position = 0; + stream.SetLength(rowValue.Length); + + var deserialized = AlgebraicValue.Deserialize(cacheTable.RowSchema, reader); + cacheTable.SetAndForgetDecodedValue(deserialized, out var obj); + results[i] = (T)obj; + } + + return results; + } + public void Update() { webSocket.Update(); @@ -728,4 +832,4 @@ public void Update() } } } -} \ No newline at end of file +} diff --git a/sdks/csharp/src/Stubs.cs b/sdks/csharp/src/Stubs.cs index 1a16795ce35..36f1ef1b9d7 100644 --- a/sdks/csharp/src/Stubs.cs +++ b/sdks/csharp/src/Stubs.cs @@ -8,18 +8,20 @@ public partial class ReducerEventBase public string ReducerName { get; private set; } public ulong Timestamp { get; private set; } public SpacetimeDB.Identity Identity { get; private set; } + public SpacetimeDB.Address? CallerAddress { get; private set; } public string ErrMessage { get; private set; } public ClientApi.Event.Types.Status Status { get; private set; } protected object Args; - public ReducerEventBase(string reducerName, ulong timestamp, SpacetimeDB.Identity identity, string errMessage, ClientApi.Event.Types.Status status, object args) + public ReducerEventBase(string reducerName, ulong timestamp, SpacetimeDB.Identity identity, SpacetimeDB.Address? callerAddress, string errMessage, ClientApi.Event.Types.Status status, object args) { ReducerName = reducerName; Timestamp = timestamp; Identity = identity; + CallerAddress = callerAddress; ErrMessage = errMessage; Status = status; Args = args; } } -} \ No newline at end of file +} diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index a9d91d31aec..21fdd388c47 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -145,10 +145,9 @@ public WebSocket(ISpacetimeDBLogger logger, ConnectOptions options) public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } - public async Task Connect(string auth, string host, string nameOrAddress, bool sslEnabled) + public async Task Connect(string auth, string host, string nameOrAddress, Address clientAddress) { - var protocol = sslEnabled ? "wss" : "ws"; - var url = new Uri($"{protocol}://{host}/database/subscribe/{nameOrAddress}"); + var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}"); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000); @@ -171,10 +170,10 @@ public async Task Connect(string auth, string host, string nameOrAddress, bool s catch (WebSocketException ex) { string message = ex.Message; - if(ex.WebSocketErrorCode == WebSocketError.NotAWebSocket) - { - // not a websocket happens when there is no module published under the address specified - message = $"{message} Did you forget to publish your module?"; + if(ex.WebSocketErrorCode == WebSocketError.NotAWebSocket) + { + // not a websocket happens when there is no module published under the address specified + message = $"{message} Did you forget to publish your module?"; } dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode, message)); return; @@ -194,10 +193,10 @@ public async Task Connect(string auth, string host, string nameOrAddress, bool s CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { - if (Ws.State != WebSocketState.Closed) - { + if (Ws.State != WebSocketState.Closed) + { await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, - CancellationToken.None); + CancellationToken.None); } dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, receiveResult.CloseStatus, null)); return; @@ -306,4 +305,4 @@ public void Update() } } } -} \ No newline at end of file +} From b2dbe89c9194f3248795b009d0a6af97fc4a6dba Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:23:50 -0500 Subject: [PATCH 056/223] Small 0.7.0 Fixes (#60) * Small update * Small fix --------- Co-authored-by: John Detter --- ...acetimeDBCSharpSDK.csproj => SpacetimeDB.ClientSDK.csproj} | 4 ++-- sdks/csharp/src/SpacetimeDBClient.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename sdks/csharp/{SpacetimeDBCSharpSDK.csproj => SpacetimeDB.ClientSDK.csproj} (87%) diff --git a/sdks/csharp/SpacetimeDBCSharpSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj similarity index 87% rename from sdks/csharp/SpacetimeDBCSharpSDK.csproj rename to sdks/csharp/SpacetimeDB.ClientSDK.csproj index af27d9f8a8f..3843bb8d137 100644 --- a/sdks/csharp/SpacetimeDBCSharpSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -12,10 +12,10 @@ SpacetimeDB The SpacetimeDB SDK is a software development kit (SDK) designed to simplify the interaction with SpacetimeDB server modules. 2023 - http://spacetimedb.com + https://spacetimedb.com logo.png README.md - https://github.com/clockworklabs/SpacetimeDBCSharpSDK + https://github.com/clockworklabs/spacetimedb-csharp-sdk 0.7.0 0.7.0 diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index df95f104150..9a158223a97 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -81,7 +81,7 @@ public struct DbOp /// /// Invoked when a reducer is returned with an error and has no client-side handler. /// - public event Action onUnhandledReducerError; + public event Action onUnhandledReducerError; /// /// Called when we receive an identity from the server From 819947c3c40578baaf9c284b65ef271f4a0d4241 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Sat, 14 Oct 2023 03:30:38 -0500 Subject: [PATCH 057/223] Small updates to 0.7.0 (#61) Co-authored-by: John Detter --- sdks/csharp/src/SpacetimeDBClient.cs | 4 +++- sdks/csharp/src/WebSocket.cs | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 9a158223a97..8f2cd0db090 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -56,7 +56,7 @@ public struct DbOp /// /// Called when a connection attempt fails. /// - public event Action onConnectError; + public event Action onConnectError; /// /// Called when an exception occurs when sending a message. @@ -822,6 +822,8 @@ T[] LogAndThrow(string error) return results; } + public bool IsConnected() => webSocket != null && webSocket.IsConnected; + public void Update() { webSocket.Update(); diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 21fdd388c47..5fd7c359c90 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -52,9 +52,9 @@ class OnConnectErrorMessage : MainThreadDispatch { private WebSocketConnectErrorEventHandler receiver; private WebSocketError? error; - private string? errorMsg; + private string errorMsg; - public OnConnectErrorMessage(WebSocketConnectErrorEventHandler receiver, WebSocketError? error, string? errorMsg) + public OnConnectErrorMessage(WebSocketConnectErrorEventHandler receiver, WebSocketError? error, string errorMsg) { this.receiver = receiver; this.error = error; @@ -107,7 +107,7 @@ public override void Execute() public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); - public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error, string? message); + public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error, string message); public delegate void WebSocketSendErrorEventHandler(Exception e); public struct ConnectOptions From 9c744a3d261facebbc152f91ca9330fe451d2ec9 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 21 Dec 2023 06:08:41 -0600 Subject: [PATCH 058/223] v0.7.2-beta Changes (#62) * Changes merged in from v0.7.1-beta * Small bug fix from stream * Updated logo file * Small bug fix related to OnBeforeDelete callback * Upgraded version to 0.7.2 --------- Co-authored-by: John Detter --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 6 +- sdks/csharp/logo.png | Bin 3485 -> 6275 bytes sdks/csharp/src/ClientCache.cs | 155 ++---- sdks/csharp/src/SpacetimeDBClient.cs | 612 ++++++++++++++++------- sdks/csharp/src/WebSocket.cs | 7 +- 5 files changed, 487 insertions(+), 293 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 3843bb8d137..bfcc1c30aa2 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -7,7 +7,7 @@ True SpacetimeDB.ClientSDK SpacetimeDB SDK - derek_clockwork + jdetter Clockwork Labs SpacetimeDB The SpacetimeDB SDK is a software development kit (SDK) designed to simplify the interaction with SpacetimeDB server modules. @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/spacetimedb-csharp-sdk - 0.7.0 - 0.7.0 + 0.7.2 + 0.7.2 diff --git a/sdks/csharp/logo.png b/sdks/csharp/logo.png index 9500cc4bcb4cb12a7072e0c81f4e64ca48de7f5c..6d65c19dba3de3cfc09915e851399d9ecf64f21c 100644 GIT binary patch literal 6275 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 eM2nH5Zu1M#PoFo5|sHwrTqtB+-9Tz diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index ca06ded6952..b60a0a705f1 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.ComponentModel.Design; -using System.Linq; -using System.Net.Http.Headers; using System.Reflection; -using Google.Protobuf; -using ClientApi; using SpacetimeDB.SATS; +using System.Numerics; +using System.Runtime.CompilerServices; namespace SpacetimeDB { @@ -19,19 +16,42 @@ public class ByteArrayComparer : IEqualityComparer { public bool Equals(byte[] left, byte[] right) { - if (left == null || right == null) + if (ReferenceEquals(left, right)) { - return left == right; + return true; } - return left.SequenceEqual(right); + if (left == null || right == null || left.Length != right.Length) + { + return false; + } + + return EqualsUnvectorized(left, right); + + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool EqualsUnvectorized(byte[] left, byte[] right) + { + for (int i = 0; i < left.Length; i++) + { + if (left[i] != right[i]) + { + return false; + } + } + + return true; } - public int GetHashCode(byte[] key) + public int GetHashCode(byte[] obj) { - if (key == null) - throw new ArgumentNullException(nameof(key)); - return key.Sum(b => b); + int hash = 17; + foreach (byte b in obj) + { + hash = hash * 31 + b; + } + return hash; } } @@ -45,9 +65,6 @@ public int GetHashCode(byte[] key) // Maps from primary key to type value public readonly Dictionary entries; - // Maps from primary key to decoded value - public readonly ConcurrentDictionary decodedValues; - public Type ClientTableType { get => clientTableType; @@ -97,48 +114,11 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func)clientTableType.GetMethod("GetPrimaryKeyType", BindingFlags.Static | BindingFlags.Public) ?.CreateDelegate(typeof(Func)); entries = new Dictionary(new ByteArrayComparer()); - decodedValues = new ConcurrentDictionary(new ByteArrayComparer()); - } - - public bool GetDecodedValue(byte[] pk, out AlgebraicValue value, out object obj) - { - if (decodedValues.TryGetValue(pk, out var decoded)) - { - value = decoded.Item1; - obj = decoded.Item2; - return true; - } - - value = null; - obj = null; - return false; } /// /// Decodes the given AlgebraicValue into the out parameter `obj`. /// - /// The primary key of the row associated with `value`. - /// The AlgebraicValue to decode. - /// The domain object for `value` - public void SetDecodedValue(byte[] pk, AlgebraicValue value, out object obj) - { - if (decodedValues.TryGetValue(pk, out var existingObj)) - { - obj = existingObj.Item2; - } - else - { - var decoded = (value, decoderFunc(value)); - decodedValues[pk] = decoded; - obj = decoded.Item2; - } - } - - /// - /// Decodes the given AlgebraicValue into the out parameter `obj`. - /// Does NOT cache the resulting value! This should only be used with rows - /// that don't participate in the usual client cache lifecycle, i.e. OneOffQuery. - /// /// The AlgebraicValue to decode. /// The domain object for `value` public void SetAndForgetDecodedValue(AlgebraicValue value, out object obj) @@ -149,38 +129,17 @@ public void SetAndForgetDecodedValue(AlgebraicValue value, out object obj) /// /// Inserts the value into the table. There can be no existing value with the provided pk. /// - /// - public object InsertEntry(byte[] rowPk) + /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. + public bool InsertEntry(byte[] rowPk, AlgebraicValue value) { - if (entries.TryGetValue(rowPk, out var existingValue)) - { - // Debug.LogWarning($"We tried to insert a database row that already exists. table={Name} RowPK={Convert.ToBase64String(rowPk)}"); - return existingValue.Item2; - } - - if (GetDecodedValue(rowPk, out var value, out var obj)) + if (entries.ContainsKey(rowPk)) { - entries[rowPk] = (value, obj); - return obj; + return false; } - - // Read failure - SpacetimeDBClient.instance.Logger.LogError( - $"Read error when converting row value for table: {clientTableType.Name} rowPk={Convert.ToBase64String(rowPk)} (version issue?)"); - return null; - } - - /// - /// Updates an entry. Returns whether or not the update was successful. Updates only succeed if - /// a previous value was overwritten. - /// - /// The primary key that uniquely identifies this row - /// The new for the table entry - /// True when the old value was removed and the new value was inserted. - public bool UpdateEntry(ByteString pk, ByteString newValueByteString) - { - // We have to figure out if pk is going to change or not - throw new InvalidOperationException(); + + // Insert the row into our table + entries[rowPk] = (value, decoderFunc(value)); + return true; } /// @@ -188,24 +147,16 @@ public bool UpdateEntry(ByteString pk, ByteString newValueByteString) /// /// The primary key that uniquely identifies this row /// - public object DeleteEntry(byte[] rowPk) + public bool DeleteEntry(byte[] rowPk) { if (entries.TryGetValue(rowPk, out var value)) { entries.Remove(rowPk); - return value.Item2; - } - - // SpacetimeDB is asking us to delete something we don't have, this makes no sense. We can - // fabricate the deletion by trying to look it up in our local decode table. - if (decodedValues.TryGetValue(rowPk, out var decodedValue)) - { - SpacetimeDBClient.instance.Logger.LogWarning("Deleting value that we don't have (using cached value)"); - return decodedValue.Item2; + return true; } SpacetimeDBClient.instance.Logger.LogWarning("Deleting value that we don't have (no cached value available)"); - return null; + return false; } /// @@ -235,23 +186,9 @@ public AlgebraicValue GetPrimaryKeyValue(AlgebraicValue row) return GetPrimaryKeyValueFunc != null ? GetPrimaryKeyValueFunc.Invoke(row) : null; } - public AlgebraicType GetPrimaryKeyType(AlgebraicType row) - { - return GetPrimaryKeyTypeFunc != null ? GetPrimaryKeyTypeFunc.Invoke(row) : null; - } - - public bool ComparePrimaryKey(byte[] rowPk1, byte[] rowPk2) + public AlgebraicType GetPrimaryKeyType() { - if (!decodedValues.TryGetValue(rowPk1, out var v1)) - { - return false; - } - if (!decodedValues.TryGetValue(rowPk2, out var v2)) - { - return false; - } - - return (bool)ComparePrimaryKeyFunc.Invoke(rowSchema, v1.Item1, v2.Item1); + return GetPrimaryKeyTypeFunc != null ? GetPrimaryKeyTypeFunc.Invoke(rowSchema) : null; } } @@ -320,5 +257,7 @@ public int Count(string name) } public IEnumerable GetTableNames() => tables.Keys; + + public IEnumerable GetTables() => tables.Values; } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 8f2cd0db090..a1d9086bff9 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -12,6 +12,8 @@ using ClientApi; using Newtonsoft.Json; using SpacetimeDB.SATS; +using Channel = System.Threading.Channels.Channel; +using Thread = System.Threading.Thread; namespace SpacetimeDB { @@ -21,7 +23,8 @@ public enum TableOp { Insert, Delete, - Update + Update, + NoChange, } public class ReducerCallRequest @@ -43,10 +46,12 @@ public struct DbOp public object oldValue; public byte[] deletedPk; public byte[] insertedPk; + public AlgebraicValue rowValue; public AlgebraicValue primaryKeyValue; } - public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, SpacetimeDB.ReducerEventBase dbEvent); + public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, + SpacetimeDB.ReducerEventBase dbEvent); /// /// Called when a connection is established to a spacetimedb instance. @@ -98,13 +103,19 @@ public struct DbOp private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; public static ClientCache clientDB; - public static Dictionary> reducerEventCache = new Dictionary>(); - public static Dictionary> deserializeEventCache = new Dictionary>(); - private static Dictionary> waitingOneOffQueries = new Dictionary>(); + public static Dictionary> reducerEventCache = + new Dictionary>(); + + public static Dictionary> deserializeEventCache = + new Dictionary>(); + + private static Dictionary> waitingOneOffQueries = + new Dictionary>(); private bool isClosing; - private Thread messageProcessThread; + private Thread networkMessageProcessThread; + private Thread stateDiffProcessThread; public static SpacetimeDBClient instance; @@ -179,7 +190,7 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) var type = typeof(IDatabaseTable); var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes()) - .Where(p => type.IsAssignableFrom(p)); + .Where(p => type.IsAssignableFrom(p)); foreach (var @class in types) { if (!@class.IsClass) @@ -190,12 +201,12 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) var algebraicTypeFunc = @class.GetMethod("GetAlgebraicType", BindingFlags.Static | BindingFlags.Public); var algebraicValue = algebraicTypeFunc!.Invoke(null, null) as AlgebraicType; var conversionFunc = @class.GetMethods() - .FirstOrDefault(a => a.Name == "op_Explicit" && - a.GetParameters().Length > 0 && - a.GetParameters()[0].ParameterType == - typeof(AlgebraicValue)); + .FirstOrDefault(a => a.Name == "op_Explicit" && + a.GetParameters().Length > 0 && + a.GetParameters()[0].ParameterType == + typeof(AlgebraicValue)); clientDB.AddTable(@class, algebraicValue, - a => { return conversionFunc!.Invoke(null, new object[] { a }); }); + a => { return conversionFunc!.Invoke(null, new object[] { a }); }); } var reducerType = FindReducerType(); @@ -207,13 +218,16 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) if (methodInfo.GetCustomAttribute() is { } reducerEvent) { - reducerEventCache.Add(reducerEvent.FunctionName, (Func)methodInfo.CreateDelegate(typeof(Func))); + reducerEventCache.Add(reducerEvent.FunctionName, + (Func)methodInfo.CreateDelegate( + typeof(Func))); } if (methodInfo.GetCustomAttribute() is { } deserializeEvent) { - deserializeEventCache.Add(deserializeEvent.FunctionName, (Action)methodInfo.CreateDelegate(typeof(Action))); + deserializeEventCache.Add(deserializeEvent.FunctionName, + (Action)methodInfo.CreateDelegate(typeof(Action))); } } } @@ -222,38 +236,40 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) loggerToUse.LogError($"Could not find reducer type. Have you run spacetime generate?"); } - _cancellationToken = _cancellationTokenSource.Token; - messageProcessThread = new Thread(ProcessMessages); - messageProcessThread.Start(); + _preProcessCancellationToken = _preProcessCancellationTokenSource.Token; + networkMessageProcessThread = new Thread(PreProcessMessages); + networkMessageProcessThread.Start(); + + _stateDiffCancellationToken = _stateDiffCancellationTokenSource.Token; + stateDiffProcessThread = new Thread(ExecuteStateDiff); + stateDiffProcessThread.Start(); } - struct ProcessedMessage + struct PreProcessedMessage { public Message message; - public IList dbOps; + public List dbOps; + public Dictionary> inserts; } - private readonly BlockingCollection _messageQueue = new BlockingCollection(new ConcurrentQueue()); - private readonly BlockingCollection _nextMessageQueue = new BlockingCollection(new ConcurrentQueue()); + private readonly BlockingCollection _messageQueue = + new BlockingCollection(new ConcurrentQueue()); - CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - CancellationToken _cancellationToken; + private readonly BlockingCollection _preProcessedNetworkMessages = + new BlockingCollection(new ConcurrentQueue()); - void ProcessMessages() + private CancellationTokenSource _preProcessCancellationTokenSource = new CancellationTokenSource(); + private CancellationToken _preProcessCancellationToken; + + void PreProcessMessages() { while (!isClosing) { try { - var bytes = _messageQueue.Take(_cancellationToken); - - var (m, events) = PreProcessMessage(bytes); - var processedMessage = new ProcessedMessage - { - message = m, - dbOps = events, - }; - _nextMessageQueue.Add(processedMessage); + var bytes = _messageQueue.Take(_preProcessCancellationToken); + var preprocessedMessage = PreProcessMessage(bytes); + _preProcessedNetworkMessages.Add(preprocessedMessage, _preProcessCancellationToken); } catch (OperationCanceledException) { @@ -262,36 +278,52 @@ void ProcessMessages() } } - (Message, List) PreProcessMessage(byte[] bytes) + PreProcessedMessage PreProcessMessage(byte[] bytes) { var dbOps = new List(); - - // Used when convering matching Insert/Delete ops into Update - var insertOps = new List(); - - var message = ClientApi.Message.Parser.ParseFrom(bytes); + var message = Message.Parser.ParseFrom(bytes); using var stream = new MemoryStream(); using var reader = new BinaryReader(stream); - SubscriptionUpdate subscriptionUpdate = null; - switch (message.TypeCase) + // This is all of the inserts + Dictionary> subscriptionInserts = null; + // All row updates that have a primary key, this contains inserts, deletes and updates + var primaryKeyChanges = new Dictionary>(); + + Dictionary GetPrimaryKeyLookup(string tableName, AlgebraicType schema) { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - subscriptionUpdate = message.SubscriptionUpdate; - break; - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; - break; + if (!primaryKeyChanges.TryGetValue(tableName, out var value)) + { + value = new Dictionary(new AlgebraicValue.AlgebraicValueComparer(schema)); + primaryKeyChanges[tableName] = value; + } + + return value; + } + + HashSet GetInsertHashSet(string tableName, int tableSize) + { + if (!subscriptionInserts.TryGetValue(tableName, out var hashSet)) + { + hashSet = new HashSet(capacity:tableSize, comparer: new ClientCache.TableCache.ByteArrayComparer()); + subscriptionInserts[tableName] = hashSet; + } + + return hashSet; } + SubscriptionUpdate subscriptionUpdate = null; switch (message.TypeCase) { case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - case ClientApi.Message.TypeOneofCase.TransactionUpdate: + subscriptionUpdate = message.SubscriptionUpdate; + subscriptionInserts = new Dictionary>( + capacity: subscriptionUpdate.TableUpdates.Sum(a => a.TableRowOperations.Count)); // First apply all of the state foreach (var update in subscriptionUpdate.TableUpdates) { var tableName = update.TableName; + var hashSet = GetInsertHashSet(tableName, subscriptionUpdate.TableUpdates.Count); var table = clientDB.GetTable(tableName); if (table == null) { @@ -299,9 +331,6 @@ void ProcessMessages() continue; } - var primaryKeyType = table.GetPrimaryKeyType(table.RowSchema); - var deleteOps = new Dictionary(new AlgebraicValue.AlgebraicValueComparer(primaryKeyType)); - insertOps.Clear(); foreach (var row in update.TableRowOperations) { var rowPk = row.RowPk.ToByteArray(); @@ -310,95 +339,149 @@ void ProcessMessages() stream.Write(rowValue, 0, rowValue.Length); stream.Position = 0; stream.SetLength(rowValue.Length); - var decodedRow = AlgebraicValue.Deserialize(table.RowSchema, reader); - if (decodedRow == null) + var deserializedRow = AlgebraicValue.Deserialize(table.RowSchema, reader); + if (deserializedRow == null) { throw new Exception("Failed to deserialize row"); } - DbOp dbOp; - AlgebraicValue primaryKeyValue = table.GetPrimaryKeyValue(decodedRow); - if (row.Op == TableRowOperation.Types.OperationType.Delete) + if (row.Op != TableRowOperation.Types.OperationType.Insert) { - dbOp = new DbOp - { - table = table, - deletedPk = rowPk, - op = TableOp.Delete, - newValue = null, - // We cannot grab the old value here because there might be other - // pending operations that will execute before us. We should only - // set this value on the main thread where we know there are no other - // operations which could remove this value. - oldValue = null, - primaryKeyValue = primaryKeyValue - }; + logger.LogWarning("Non-insert during a subscription update!"); + continue; + } + + table.SetAndForgetDecodedValue(deserializedRow, out var obj); + var op = new DbOp + { + table = table, + deletedPk = null, + insertedPk = rowPk, + op = TableOp.Insert, + newValue = obj, + oldValue = null, + primaryKeyValue = null, + rowValue = deserializedRow, + }; + + if (!hashSet.Add(rowPk)) + { + logger.LogError($"Multiple of the same insert in the same subscription update: table={table.Name} rowPk={rowPk}"); } else { - // Skip this insert if we already have it - if (table.entries.ContainsKey(rowPk)) - { - continue; - } + dbOps.Add(op); + } + } + } - table.SetDecodedValue(rowPk, decodedRow, out var obj); - dbOp = new DbOp - { - table = table, - insertedPk = rowPk, - op = TableOp.Insert, - newValue = obj, - oldValue = null, - primaryKeyValue = primaryKeyValue - }; + break; + + case ClientApi.Message.TypeOneofCase.TransactionUpdate: + subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; + // First apply all of the state + foreach (var update in subscriptionUpdate.TableUpdates) + { + var tableName = update.TableName; + var table = clientDB.GetTable(tableName); + if (table == null) + { + logger.LogError($"Unknown table name: {tableName}"); + continue; + } + + foreach (var row in update.TableRowOperations) + { + var rowPk = row.RowPk.ToByteArray(); + var rowValue = row.Row.ToByteArray(); + stream.Position = 0; + stream.Write(rowValue, 0, rowValue.Length); + stream.Position = 0; + stream.SetLength(rowValue.Length); + var deserializedRow = AlgebraicValue.Deserialize(table.RowSchema, reader); + if (deserializedRow == null) + { + throw new Exception("Failed to deserialize row"); } + var primaryKeyValue = table.GetPrimaryKeyValue(deserializedRow); + var primaryKeyType = table.GetPrimaryKeyType(); + table.SetAndForgetDecodedValue(deserializedRow, out var obj); + + var op = new DbOp + { + table = table, + deletedPk = + row.Op == TableRowOperation.Types.OperationType.Delete ? rowPk : null, + insertedPk = + row.Op == TableRowOperation.Types.OperationType.Delete ? null : rowPk, + op = row.Op == TableRowOperation.Types.OperationType.Delete + ? TableOp.Delete + : TableOp.Insert, + newValue = row.Op == TableRowOperation.Types.OperationType.Delete ? null : obj, + oldValue = row.Op == TableRowOperation.Types.OperationType.Delete ? obj : null, + primaryKeyValue = primaryKeyValue, + rowValue = deserializedRow, + }; + if (primaryKeyType != null) { - if (row.Op == TableRowOperation.Types.OperationType.Delete) + var primaryKeyLookup = GetPrimaryKeyLookup(tableName, primaryKeyType); + if (primaryKeyLookup.TryGetValue(primaryKeyValue, out var value)) { - deleteOps[primaryKeyValue] = dbOp; + if (value.op == op.op || value.op == TableOp.Update) + { + logger.LogWarning($"Update with the same primary key was " + + $"applied multiple times! tableName={tableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. + continue; + } + + var insertOp = op; + var deleteOp = value; + if (op.op == TableOp.Delete) + { + insertOp = value; + deleteOp = op; + } + + primaryKeyLookup[primaryKeyValue] = new DbOp + { + table = insertOp.table, + op = TableOp.Update, + newValue = insertOp.newValue, + oldValue = deleteOp.oldValue, + deletedPk = deleteOp.deletedPk, + insertedPk = insertOp.insertedPk, + primaryKeyValue = insertOp.primaryKeyValue, + rowValue = insertOp.rowValue, + }; } else { - insertOps.Add(dbOp); + primaryKeyLookup[primaryKeyValue] = op; } } else { - dbOps.Add(dbOp); + dbOps.Add(op); } } + } - if (primaryKeyType != null) - { - // Replace Delete/Insert pairs with identical primary keys with an Update. - // - // !!TODO!!: Currently this code interprets Insert/Delete or Delete/Insert pairs as Updates. - // Note that if a user inserts and then deletes a row with the same primary key in a - // spacetimedb module, this is interpreted as an Update, while effectively it is a NoOp. - for (var i = 0; i < insertOps.Count; i++) - { - var insertOp = insertOps[i]; - if (deleteOps.TryGetValue(insertOp.primaryKeyValue, out var deleteOp)) - { - // We found an insert with a matching delete. - // Replace it with an update operation. - insertOps[i] = new DbOp - { - insertedPk = insertOp.insertedPk, - deletedPk = deleteOp.deletedPk, - table = insertOp.table, - op = TableOp.Update - }; - deleteOps.Remove(insertOp.primaryKeyValue); - } - } - dbOps.AddRange(insertOps); - dbOps.AddRange(deleteOps.Values); - } + // Combine primary key updates and non-primary key updates + dbOps.AddRange(primaryKeyChanges.Values.SelectMany(a => a.Values)); + + // Convert the generic event arguments in to a domain specific event object, this gets fed back into + // the message.TransactionUpdate.Event.FunctionCall.CallInfo field. + if (message.TypeCase == Message.TypeOneofCase.TransactionUpdate && + deserializeEventCache.TryGetValue(message.TransactionUpdate.Event.FunctionCall.Reducer, + out var deserializer)) + { + deserializer.Invoke(message.TransactionUpdate.Event); } + break; case ClientApi.Message.TypeOneofCase.IdentityToken: break; @@ -416,46 +499,97 @@ void ProcessMessages() logger.LogError("Response to unknown one-off-query: " + messageId); break; } + waitingOneOffQueries[messageId].Writer.TryWrite(resp); waitingOneOffQueries.Remove(messageId); break; } - if (message.TypeCase == Message.TypeOneofCase.SubscriptionUpdate) + + // logger.LogWarning($"Total Updates preprocessed: {totalUpdateCount}"); + return new PreProcessedMessage { message = message, dbOps = dbOps, inserts = subscriptionInserts }; + } + } + + struct ProcessedMessage + { + public Message message; + public List dbOps; + public HashSet inserts; + } + + // The lock that must be acquired in order to manipulate _stateDiffMessage + private object _stateDiffLock = new object(); + + // The message that has been preprocessed and has had its state diff calculated + private ProcessedMessage? _stateDiffMessage = null; + + private CancellationTokenSource _stateDiffCancellationTokenSource = new CancellationTokenSource(); + private CancellationToken _stateDiffCancellationToken; + + void ExecuteStateDiff() + { + while (!isClosing) + { + try { - // NOTE: We are going to calculate a local state diff here. This is kind of expensive to do, - // but keep in mind that we're still on the network thread so spending some extra time here - // is acceptable. - if (subscriptionUpdate!.TableUpdates.Any( - a => a.TableRowOperations.Any(b => b.Op == TableRowOperation.Types.OperationType.Delete))) + lock (_stateDiffLock) { - logger.LogWarning( - "We see delete events in our subscription update, this is unexpected. Likely you should update your SpacetimeDBUnitySDK."); + while (_stateDiffMessage != null) + { + Monitor.Wait(_stateDiffLock); + } } - - foreach (var tableUpdate in subscriptionUpdate.TableUpdates) + + var message = _preProcessedNetworkMessages.Take(_stateDiffCancellationToken); + var (m, events) = CalculateStateDiff(message); + + lock (_stateDiffLock) { - var clientTable = clientDB.GetTable(tableUpdate.TableName); - var newPks = tableUpdate.TableRowOperations - .Where(a => a.Op == TableRowOperation.Types.OperationType.Insert) - .Select(b => b.RowPk.ToByteArray()); - var existingPks = clientTable.entries.Select(a => a.Key); - dbOps.AddRange(existingPks.Except(newPks, new ClientCache.TableCache.ByteArrayComparer()) - .Select(a => new DbOp - { - deletedPk = a, - newValue = null, - oldValue = clientTable.entries[a].Item2, - op = TableOp.Delete, - table = clientTable, - })); + _stateDiffMessage = new ProcessedMessage { dbOps = events, message = m, }; } } + catch (OperationCanceledException) + { + // Normal shutdown + return; + } + } - if (message.TypeCase == Message.TypeOneofCase.TransactionUpdate && - deserializeEventCache.TryGetValue(message.TransactionUpdate.Event.FunctionCall.Reducer, out var deserializer)) + (Message, List) CalculateStateDiff(PreProcessedMessage preProcessedMessage) + { + var message = preProcessedMessage.message; + var dbOps = preProcessedMessage.dbOps; + // Perform the state diff, this has to be done on the main thread because we have to touch + // the client cache. + if (message.TypeCase == Message.TypeOneofCase.SubscriptionUpdate) { - deserializer.Invoke(message.TransactionUpdate.Event); + foreach (var table in clientDB.GetTables()) + { + foreach (var rowPk in table.entries.Keys) + { + if (!preProcessedMessage.inserts.TryGetValue(table.Name, out var hashSet)) + { + continue; + } + + if (!hashSet.Contains(rowPk)) + { + // This is a row that we had before, but we do not have it now. + // This must have been a delete. + dbOps.Add(new DbOp + { + table = table, + op = TableOp.Delete, + newValue = null, + oldValue = table.entries[rowPk].Item2, + deletedPk = rowPk, + insertedPk = null, + primaryKeyValue = null + }); + } + } + } } return (message, dbOps); @@ -467,7 +601,13 @@ public void Close() isClosing = true; connectionClosed = true; webSocket.Close(); - _cancellationTokenSource.Cancel(); + _preProcessCancellationTokenSource.Cancel(); + _stateDiffCancellationTokenSource.Cancel(); + lock (_stateDiffLock) + { + Monitor.Pulse(_stateDiffLock); + } + webSocket = null; } @@ -507,22 +647,21 @@ public void Connect(string token, string uri, string addressOrName) }); } - private void OnMessageProcessComplete(Message message, IList dbOps) + private void OnMessageProcessComplete(Message message, List dbOps) { switch (message.TypeCase) { case Message.TypeOneofCase.SubscriptionUpdate: case Message.TypeOneofCase.TransactionUpdate: // First trigger OnBeforeDelete - for (var i = 0; i < dbOps.Count; i++) + foreach (var update in dbOps) { - // TODO: Reimplement updates when we add support for primary keys - var update = dbOps[i]; - if (update.op == TableOp.Delete && update.table.TryGetValue(update.deletedPk, out var oldVal)) + if (update.op == TableOp.Delete) { try { - update.table.BeforeDeleteCallback?.Invoke(oldVal, message.TransactionUpdate?.Event); + update.table.BeforeDeleteCallback?.Invoke(update.oldValue, + message.TransactionUpdate?.Event); } catch (Exception e) { @@ -531,6 +670,30 @@ private void OnMessageProcessComplete(Message message, IList dbOps) } } + void InternalDeleteCallback(DbOp op) + { + if (op.oldValue != null) + { + op.table.InternalValueDeletedCallback(op.oldValue); + } + else + { + logger.LogError("Delete issued, but no value was present!"); + } + } + + void InternalInsertCallback(DbOp op) + { + if (op.newValue != null) + { + op.table.InternalValueInsertedCallback(op.newValue); + } + else + { + logger.LogError("Insert issued, but no value was present!"); + } + } + // Apply all of the state for (var i = 0; i < dbOps.Count; i++) { @@ -539,27 +702,51 @@ private void OnMessageProcessComplete(Message message, IList dbOps) switch (update.op) { case TableOp.Delete: - update.oldValue = dbOps[i].table.DeleteEntry(update.deletedPk); - if (update.oldValue != null) + if (dbOps[i].table.DeleteEntry(update.deletedPk)) + { + InternalDeleteCallback(update); + } + else { - update.table.InternalValueDeletedCallback(update.oldValue); + var op = dbOps[i]; + op.op = TableOp.NoChange; + dbOps[i] = op; } - dbOps[i] = update; break; case TableOp.Insert: - update.newValue = dbOps[i].table.InsertEntry(update.insertedPk); - update.table.InternalValueInsertedCallback(update.newValue); - dbOps[i] = update; + if (dbOps[i].table.InsertEntry(update.insertedPk, update.rowValue)) + { + InternalInsertCallback(update); + } + else + { + var op = dbOps[i]; + op.op = TableOp.NoChange; + dbOps[i] = op; + } break; case TableOp.Update: - update.oldValue = dbOps[i].table.DeleteEntry(update.deletedPk); - update.newValue = dbOps[i].table.InsertEntry(update.insertedPk); - if (update.oldValue != null) + if (dbOps[i].table.DeleteEntry(update.deletedPk)) + { + InternalDeleteCallback(update); + } + else + { + var op = dbOps[i]; + op.op = TableOp.NoChange; + dbOps[i] = op; + } + + if (dbOps[i].table.InsertEntry(update.insertedPk, update.rowValue)) + { + InternalInsertCallback(update); + } + else { - update.table.InternalValueDeletedCallback(update.oldValue); + var op = dbOps[i]; + op.op = TableOp.NoChange; + dbOps[i] = op; } - update.table.InternalValueInsertedCallback(update.newValue); - dbOps[i] = update; break; default: throw new ArgumentOutOfRangeException(); @@ -584,7 +771,8 @@ private void OnMessageProcessComplete(Message message, IList dbOps) { if (dbOps[i].table.InsertCallback != null) { - dbOps[i].table.InsertCallback.Invoke(newValue, message.TransactionUpdate?.Event); + dbOps[i].table.InsertCallback.Invoke(newValue, + message.TransactionUpdate?.Event); } } catch (Exception e) @@ -604,7 +792,6 @@ private void OnMessageProcessComplete(Message message, IList dbOps) { logger.LogException(e); } - } else { @@ -620,7 +807,8 @@ private void OnMessageProcessComplete(Message message, IList dbOps) { try { - dbOps[i].table.DeleteCallback.Invoke(oldValue, message.TransactionUpdate?.Event); + dbOps[i].table.DeleteCallback.Invoke(oldValue, + message.TransactionUpdate?.Event); } catch (Exception e) { @@ -656,7 +844,8 @@ private void OnMessageProcessComplete(Message message, IList dbOps) { if (dbOps[i].table.UpdateCallback != null) { - dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, message.TransactionUpdate?.Event); + dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, + message.TransactionUpdate?.Event); } } catch (Exception e) @@ -669,7 +858,7 @@ private void OnMessageProcessComplete(Message message, IList dbOps) if (dbOps[i].table.RowUpdatedCallback != null) { dbOps[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); + .Invoke(tableOp, oldValue, newValue, message.TransactionUpdate?.Event); } } catch (Exception e) @@ -684,30 +873,69 @@ private void OnMessageProcessComplete(Message message, IList dbOps) break; } + case TableOp.NoChange: + // noop + break; default: throw new ArgumentOutOfRangeException(); } - onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue, message.Event?.FunctionCall.CallInfo); + if (tableOp != TableOp.NoChange) + { + onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue, + message.Event?.FunctionCall.CallInfo); + } } switch (message.TypeCase) { case Message.TypeOneofCase.SubscriptionUpdate: - onSubscriptionApplied?.Invoke(); + try + { + onSubscriptionApplied?.Invoke(); + } + catch (Exception e) + { + logger.LogException(e); + } + break; case Message.TypeOneofCase.TransactionUpdate: - onEvent?.Invoke(message.TransactionUpdate.Event); + try + { + onEvent?.Invoke(message.TransactionUpdate.Event); + } + catch (Exception e) + { + logger.LogException(e); + } bool reducerFound = false; var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; if (reducerEventCache.TryGetValue(functionName, out var value)) { - reducerFound = value.Invoke(message.TransactionUpdate.Event); + try + { + reducerFound = value.Invoke(message.TransactionUpdate.Event); + } + catch (Exception e) + { + logger.LogException(e); + } } - if (!reducerFound && message.TransactionUpdate.Event.Status == ClientApi.Event.Types.Status.Failed) + + if (!reducerFound && message.TransactionUpdate.Event.Status == + ClientApi.Event.Types.Status.Failed) { - onUnhandledReducerError?.Invoke(message.TransactionUpdate.Event.FunctionCall.CallInfo); + try + { + onUnhandledReducerError?.Invoke(message.TransactionUpdate.Event.FunctionCall + .CallInfo); + } + catch (Exception e) + { + logger.LogException(e); + } } break; @@ -725,10 +953,28 @@ private void OnMessageProcessComplete(Message message, IList dbOps) break; case Message.TypeOneofCase.IdentityToken: - onIdentityReceived?.Invoke(message.IdentityToken.Token, Identity.From(message.IdentityToken.Identity.ToByteArray()), (Address)Address.From(message.IdentityToken.Address.ToByteArray())); + try + { + onIdentityReceived?.Invoke(message.IdentityToken.Token, + Identity.From(message.IdentityToken.Identity.ToByteArray()), + (Address)Address.From(message.IdentityToken.Address.ToByteArray())); + } + catch (Exception e) + { + logger.LogException(e); + } + break; case Message.TypeOneofCase.Event: - onEvent?.Invoke(message.Event); + try + { + onEvent?.Invoke(message.Event); + } + catch (Exception e) + { + logger.LogException(e); + } + break; } } @@ -742,6 +988,7 @@ public void InternalCallReducer(string json) logger.LogError("Cannot call reducer, not connected to server!"); return; } + webSocket.Send(Encoding.ASCII.GetBytes("{ \"call\": " + json + " }")); } @@ -752,6 +999,7 @@ public void Subscribe(List queries) logger.LogError("Cannot subscribe, not connected to server!"); return; } + var json = JsonConvert.SerializeObject(queries); // should we use UTF8 here? ASCII is fragile. webSocket.Send(Encoding.ASCII.GetBytes("{ \"subscribe\": { \"query_strings\": " + json + " }}")); @@ -770,8 +1018,9 @@ public async Task OneOffQuery(string query) where T : IDatabaseTable string queryString = "SELECT * FROM " + type.Name + " " + query; // see: SpacetimeDB\crates\core\src\client\message_handlers.rs, enum Message<'a> - var serializedQuery = "{ \"one_off_query\": { \"message_id\": \"" + System.Convert.ToBase64String(messageId.ToByteArray()) + - "\", \"query_string\": " + JsonConvert.SerializeObject(queryString) + " } }"; + var serializedQuery = "{ \"one_off_query\": { \"message_id\": \"" + + System.Convert.ToBase64String(messageId.ToByteArray()) + + "\", \"query_string\": " + JsonConvert.SerializeObject(queryString) + " } }"; webSocket.Send(Encoding.UTF8.GetBytes(serializedQuery)); // Suspend for an arbitrary amount of time @@ -828,9 +1077,14 @@ public void Update() { webSocket.Update(); - while (_nextMessageQueue.TryTake(out var nextMessage)) + lock (_stateDiffLock) { - OnMessageProcessComplete(nextMessage.message, nextMessage.dbOps); + if (_stateDiffMessage != null) + { + OnMessageProcessComplete(_stateDiffMessage.Value.message, _stateDiffMessage.Value.dbOps); + _stateDiffMessage = null; + Monitor.Pulse(_stateDiffLock); + } } } } diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 5fd7c359c90..b2ffb29521b 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -52,9 +52,9 @@ class OnConnectErrorMessage : MainThreadDispatch { private WebSocketConnectErrorEventHandler receiver; private WebSocketError? error; - private string errorMsg; + private string? errorMsg; - public OnConnectErrorMessage(WebSocketConnectErrorEventHandler receiver, WebSocketError? error, string errorMsg) + public OnConnectErrorMessage(WebSocketConnectErrorEventHandler receiver, WebSocketError? error, string? errorMsg) { this.receiver = receiver; this.error = error; @@ -107,7 +107,7 @@ public override void Execute() public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); - public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error, string message); + public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error, string? message); public delegate void WebSocketSendErrorEventHandler(Exception e); public struct ConnectOptions @@ -175,6 +175,7 @@ public async Task Connect(string auth, string host, string nameOrAddress, Addres // not a websocket happens when there is no module published under the address specified message = $"{message} Did you forget to publish your module?"; } + _logger.LogException(ex); dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode, message)); return; } From f3159602b28f41aa9ea06846d9861ea458923608 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 21 Dec 2023 09:16:32 -0600 Subject: [PATCH 059/223] Workflow for Publishing Nuget Package (#64) * Committing script for building nuget package * Script replaced with github action workflow * On pull requests as well * Bump version * Updated build config * Ready to test --------- Co-authored-by: John Detter --- .../.github/workflows/publish-nuget.yml | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 sdks/csharp/.github/workflows/publish-nuget.yml diff --git a/sdks/csharp/.github/workflows/publish-nuget.yml b/sdks/csharp/.github/workflows/publish-nuget.yml new file mode 100644 index 00000000000..04f0a141146 --- /dev/null +++ b/sdks/csharp/.github/workflows/publish-nuget.yml @@ -0,0 +1,25 @@ +name: Publish NuGet Package on Release + +on: + release: + types: [published] + +jobs: + build-and-publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8' + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore --configuration Release + # - name: Test + # run: dotnet test --no-build + - name: Pack + run: dotnet pack --no-build --output nupkgs + - name: Publish + run: dotnet nuget push nupkgs/*.nupkg --api-key ${{secrets.NUGET_API_KEY}} --source https://api.nuget.org/v3/index.json From d54c31a47c13ec15836a9d892728178e7ccc1549 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 21 Dec 2023 09:17:38 -0600 Subject: [PATCH 060/223] Upgraded version to 0.8.0 (#66) Co-authored-by: John Detter --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index bfcc1c30aa2..b47ff21391c 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/spacetimedb-csharp-sdk - 0.7.2 - 0.7.2 + 0.8.0 + 0.8.0 From b1705390f37a94bfa974924e517bb47457e82ec6 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Tue, 6 Feb 2024 12:50:05 -0600 Subject: [PATCH 061/223] Fixed an issue where only one network packet was being processed per (#70) frame Co-authored-by: John Detter --- sdks/csharp/src/SpacetimeDBClient.cs | 35 ++++------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index a1d9086bff9..3367b94ee63 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -518,12 +518,9 @@ struct ProcessedMessage public HashSet inserts; } - // The lock that must be acquired in order to manipulate _stateDiffMessage - private object _stateDiffLock = new object(); - // The message that has been preprocessed and has had its state diff calculated - private ProcessedMessage? _stateDiffMessage = null; - + + private BlockingCollection _stateDiffMessages = new BlockingCollection(); private CancellationTokenSource _stateDiffCancellationTokenSource = new CancellationTokenSource(); private CancellationToken _stateDiffCancellationToken; @@ -533,21 +530,9 @@ void ExecuteStateDiff() { try { - lock (_stateDiffLock) - { - while (_stateDiffMessage != null) - { - Monitor.Wait(_stateDiffLock); - } - } - var message = _preProcessedNetworkMessages.Take(_stateDiffCancellationToken); var (m, events) = CalculateStateDiff(message); - - lock (_stateDiffLock) - { - _stateDiffMessage = new ProcessedMessage { dbOps = events, message = m, }; - } + _stateDiffMessages.Add(new ProcessedMessage { dbOps = events, message = m, }); } catch (OperationCanceledException) { @@ -603,10 +588,6 @@ public void Close() webSocket.Close(); _preProcessCancellationTokenSource.Cancel(); _stateDiffCancellationTokenSource.Cancel(); - lock (_stateDiffLock) - { - Monitor.Pulse(_stateDiffLock); - } webSocket = null; } @@ -1076,15 +1057,9 @@ T[] LogAndThrow(string error) public void Update() { webSocket.Update(); - - lock (_stateDiffLock) + while (_stateDiffMessages.TryTake(out var stateDiffMessage)) { - if (_stateDiffMessage != null) - { - OnMessageProcessComplete(_stateDiffMessage.Value.message, _stateDiffMessage.Value.dbOps); - _stateDiffMessage = null; - Monitor.Pulse(_stateDiffLock); - } + OnMessageProcessComplete(stateDiffMessage.message, stateDiffMessage.dbOps); } } } From 061f1c3fbfcafc0e460d9c176be836bd49e61669 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:09:54 -0600 Subject: [PATCH 062/223] Added new callback - onBeforeSubscriptionApplied (#71) * onBeforeSubscriptionApplied * Small bug fix --------- Co-authored-by: John Detter --- sdks/csharp/src/SpacetimeDBClient.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 3367b94ee63..dc4f412e4f8 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -78,6 +78,11 @@ public delegate void RowUpdate(string tableName, TableOp op, object oldValue, ob /// public event RowUpdate onRowUpdate; + /// + /// Invoked when a subscription is about to start being processed. This is called even before OnBeforeDelete. + /// + public event Action onBeforeSubscriptionApplied; + /// /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. /// @@ -630,6 +635,13 @@ public void Connect(string token, string uri, string addressOrName) private void OnMessageProcessComplete(Message message, List dbOps) { + switch (message.TypeCase) + { + case Message.TypeOneofCase.SubscriptionUpdate: + onBeforeSubscriptionApplied?.Invoke(); + break; + } + switch (message.TypeCase) { case Message.TypeOneofCase.SubscriptionUpdate: From 75dc6b59b012265759a671cdab490b5a94f0b7fb Mon Sep 17 00:00:00 2001 From: Phoebe Goldman Date: Wed, 28 Feb 2024 13:56:38 -0500 Subject: [PATCH 063/223] Remove the `rowPk` from the client API (#72) Re: https://github.com/clockworklabs/SpacetimeDB/pull/840 This commit updates the C# SDK to no longer use the `row_pk` field of the Protobuf client API, as that field has been removed. (Will have been removed, as of merging.) Where a table cache was previously keyed on `byte[] rowPk`, it is now keyed on `byte[] rowBytes`, where `rowBytes` is the BSATN-encoded bytes of the row. This means we effectively store two copies of each row in the client cache: the BSATN serialized format, and the decoded domain type. An alternate implementation would be to make the table caches be sets of domain types, discarding the BSATN bytes. We find this undesirable for several reasons: - Hashing and equality-comparing `byte[]` is almost certainly more efficient than doing the same for domain types. - Even if hashing and equality-comparing domain types were efficient, we would still have to update codegen to emit hashing and equality methods for all types in the module_bindings. This implementation requires no changes to the module_bindings. - We already have the BSATN bytes sitting around, as they're necessarily part of the message we recieve from the server. This change does no additional serialization or deserialization. In essence, we're trading memory for time and simplicity. Keeping the BSATN bytes live approximately doubles the table cache's memory usage, but simplifies the implementation greatly, and (we suspect) speeds up table cache insertions, deletions and lookups. --- sdks/csharp/DEVELOP.md | 17 +++++ .../examples/quickstart/client/client.csproj | 2 +- .../client/module_bindings/Message.cs | 1 + .../client/module_bindings/Reducer.cs | 7 -- .../module_bindings/ReducerJsonSettings.cs | 1 + .../quickstart/client/module_bindings/User.cs | 13 ++++ sdks/csharp/src/ClientApi.cs | 64 ++++--------------- sdks/csharp/src/ClientCache.cs | 29 +++++---- sdks/csharp/src/SpacetimeDBClient.cs | 56 ++++++++-------- 9 files changed, 87 insertions(+), 103 deletions(-) create mode 100644 sdks/csharp/DEVELOP.md delete mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/Reducer.cs diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md new file mode 100644 index 00000000000..de08bc707b4 --- /dev/null +++ b/sdks/csharp/DEVELOP.md @@ -0,0 +1,17 @@ +# Notes for maintainers + +## `ClientApi.cs` + +The file `ClientApi.cs` is generated by [ProtoBuf](https://protobuf.dev/) +from [the SpacetimeDB client-api-messages proto definition](https://github.com/clockworklabs/SpacetimeDB/blob/master/crates/client-api-messages/protobuf/client_api.proto). +This is not automated. +Whenever the `client_api.proto` changes, you'll have to manually re-run `protoc` to re-generate the definitions. + +```sh +cd ~/clockworklabs/SpacetimeDB/crates/client-api-messages/protobuf +protoc --csharp_out=/absolute/path/to/spacetimedb-csharp-sdk/src \ + ./client_api.proto +``` + +Note that `protoc` cannot understand paths that start with `~`; +you must write the absolute path starting from `/`. diff --git a/sdks/csharp/examples/quickstart/client/client.csproj b/sdks/csharp/examples/quickstart/client/client.csproj index b5bf94d5eda..765c83b1394 100644 --- a/sdks/csharp/examples/quickstart/client/client.csproj +++ b/sdks/csharp/examples/quickstart/client/client.csproj @@ -10,7 +10,7 @@ - + diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs index eb383376d3a..25800e8f19a 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs @@ -7,6 +7,7 @@ namespace SpacetimeDB.Types { + [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)] public partial class Message : IDatabaseTable { [Newtonsoft.Json.JsonProperty("sender")] diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Reducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/Reducer.cs deleted file mode 100644 index f25e5e07b71..00000000000 --- a/sdks/csharp/examples/quickstart/client/module_bindings/Reducer.cs +++ /dev/null @@ -1,7 +0,0 @@ -using SpacetimeDB; - -namespace SpacetimeDB.Types -{ - [ReducerClass] - public partial class Reducer { } -} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs index d42b1a5d46e..f05fa36edee 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs @@ -2,6 +2,7 @@ namespace SpacetimeDB.Types { + [ReducerClass] public partial class Reducer { private static Newtonsoft.Json.JsonSerializerSettings _settings = new Newtonsoft.Json.JsonSerializerSettings diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs index 503340016e8..85c7ca12b7d 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs @@ -7,6 +7,7 @@ namespace SpacetimeDB.Types { + [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)] public partial class User : IDatabaseTable { [Newtonsoft.Json.JsonProperty("identity")] @@ -81,6 +82,18 @@ public static User FilterByIdentity(SpacetimeDB.Identity value) return r; } + public static System.Collections.Generic.IEnumerable FilterByName(string? value) + { + foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("User")) + { + var productValue = entry.Item1.AsProductValue(); + var compareValue = (string?)(productValue.elements[1].AsSumValue().tag == 1 ? null : productValue.elements[1].AsSumValue().value.AsString()); + if (compareValue == value) { + yield return (User)entry.Item2; + } + } + } + public static System.Collections.Generic.IEnumerable FilterByOnline(bool value) { foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("User")) diff --git a/sdks/csharp/src/ClientApi.cs b/sdks/csharp/src/ClientApi.cs index a8b3ec3460a..ee8f38bc94a 100644 --- a/sdks/csharp/src/ClientApi.cs +++ b/sdks/csharp/src/ClientApi.cs @@ -48,18 +48,17 @@ static ClientApiReflection() { "ZGF0ZRItCgx0YWJsZVVwZGF0ZXMYASADKAsyFy5jbGllbnRfYXBpLlRhYmxl", "VXBkYXRlImwKC1RhYmxlVXBkYXRlEg8KB3RhYmxlSWQYASABKA0SEQoJdGFi", "bGVOYW1lGAIgASgJEjkKEnRhYmxlUm93T3BlcmF0aW9ucxgDIAMoCzIdLmNs", - "aWVudF9hcGkuVGFibGVSb3dPcGVyYXRpb24ikgEKEVRhYmxlUm93T3BlcmF0", + "aWVudF9hcGkuVGFibGVSb3dPcGVyYXRpb24iggEKEVRhYmxlUm93T3BlcmF0", "aW9uEjcKAm9wGAEgASgOMisuY2xpZW50X2FwaS5UYWJsZVJvd09wZXJhdGlv", - "bi5PcGVyYXRpb25UeXBlEg4KBnJvd19waxgCIAEoDBILCgNyb3cYAyABKAwi", - "JwoNT3BlcmF0aW9uVHlwZRIKCgZERUxFVEUQABIKCgZJTlNFUlQQASJxChFU", - "cmFuc2FjdGlvblVwZGF0ZRIgCgVldmVudBgBIAEoCzIRLmNsaWVudF9hcGku", - "RXZlbnQSOgoSc3Vic2NyaXB0aW9uVXBkYXRlGAIgASgLMh4uY2xpZW50X2Fw", - "aS5TdWJzY3JpcHRpb25VcGRhdGUiNQoLT25lT2ZmUXVlcnkSEQoJbWVzc2Fn", - "ZUlkGAEgASgMEhMKC3F1ZXJ5U3RyaW5nGAIgASgJImAKE09uZU9mZlF1ZXJ5", - "UmVzcG9uc2USEQoJbWVzc2FnZUlkGAEgASgMEg0KBWVycm9yGAIgASgJEicK", - "BnRhYmxlcxgDIAMoCzIXLmNsaWVudF9hcGkuT25lT2ZmVGFibGUiLQoLT25l", - "T2ZmVGFibGUSEQoJdGFibGVOYW1lGAIgASgJEgsKA3JvdxgEIAMoDGIGcHJv", - "dG8z")); + "bi5PcGVyYXRpb25UeXBlEgsKA3JvdxgDIAEoDCInCg1PcGVyYXRpb25UeXBl", + "EgoKBkRFTEVURRAAEgoKBklOU0VSVBABInEKEVRyYW5zYWN0aW9uVXBkYXRl", + "EiAKBWV2ZW50GAEgASgLMhEuY2xpZW50X2FwaS5FdmVudBI6ChJzdWJzY3Jp", + "cHRpb25VcGRhdGUYAiABKAsyHi5jbGllbnRfYXBpLlN1YnNjcmlwdGlvblVw", + "ZGF0ZSI1CgtPbmVPZmZRdWVyeRIRCgltZXNzYWdlSWQYASABKAwSEwoLcXVl", + "cnlTdHJpbmcYAiABKAkiYAoTT25lT2ZmUXVlcnlSZXNwb25zZRIRCgltZXNz", + "YWdlSWQYASABKAwSDQoFZXJyb3IYAiABKAkSJwoGdGFibGVzGAMgAygLMhcu", + "Y2xpZW50X2FwaS5PbmVPZmZUYWJsZSItCgtPbmVPZmZUYWJsZRIRCgl0YWJs", + "ZU5hbWUYAiABKAkSCwoDcm93GAQgAygMYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { @@ -70,7 +69,7 @@ static ClientApiReflection() { new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Event), global::ClientApi.Event.Parser, new[]{ "Timestamp", "CallerIdentity", "FunctionCall", "Status", "Message", "EnergyQuantaUsed", "HostExecutionDurationMicros", "CallerAddress" }, null, new[]{ typeof(global::ClientApi.Event.Types.Status) }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.SubscriptionUpdate), global::ClientApi.SubscriptionUpdate.Parser, new[]{ "TableUpdates" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableUpdate), global::ClientApi.TableUpdate.Parser, new[]{ "TableId", "TableName", "TableRowOperations" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableRowOperation), global::ClientApi.TableRowOperation.Parser, new[]{ "Op", "RowPk", "Row" }, null, new[]{ typeof(global::ClientApi.TableRowOperation.Types.OperationType) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableRowOperation), global::ClientApi.TableRowOperation.Parser, new[]{ "Op", "Row" }, null, new[]{ typeof(global::ClientApi.TableRowOperation.Types.OperationType) }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TransactionUpdate), global::ClientApi.TransactionUpdate.Parser, new[]{ "Event", "SubscriptionUpdate" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQuery), global::ClientApi.OneOffQuery.Parser, new[]{ "MessageId", "QueryString" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQueryResponse), global::ClientApi.OneOffQueryResponse.Parser, new[]{ "MessageId", "Error", "Tables" }, null, null, null, null), @@ -2401,10 +2400,6 @@ public void MergeFrom(pb::CodedInputStream input) { //// - `op` of `INSERT` means that the row in question has been either newly inserted or //// updated, and is resident in the table. //// - //// - `row_pk` is a hash of the row computed by the database. As of 2023-06-13, even for - //// tables with a `#[primarykey]` annotation on one column, the `row_pk` is not - //// that primary key. - //// //// - `row` is the row itself, encoded as BSATN. /// public sealed partial class TableRowOperation : pb::IMessage @@ -2442,7 +2437,6 @@ public TableRowOperation() { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TableRowOperation(TableRowOperation other) : this() { op_ = other.op_; - rowPk_ = other.rowPk_; row_ = other.row_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -2465,18 +2459,6 @@ public TableRowOperation Clone() { } } - /// Field number for the "row_pk" field. - public const int RowPkFieldNumber = 2; - private pb::ByteString rowPk_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString RowPk { - get { return rowPk_; } - set { - rowPk_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - /// Field number for the "row" field. public const int RowFieldNumber = 3; private pb::ByteString row_ = pb::ByteString.Empty; @@ -2505,7 +2487,6 @@ public bool Equals(TableRowOperation other) { return true; } if (Op != other.Op) return false; - if (RowPk != other.RowPk) return false; if (Row != other.Row) return false; return Equals(_unknownFields, other._unknownFields); } @@ -2515,7 +2496,6 @@ public bool Equals(TableRowOperation other) { public override int GetHashCode() { int hash = 1; if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) hash ^= Op.GetHashCode(); - if (RowPk.Length != 0) hash ^= RowPk.GetHashCode(); if (Row.Length != 0) hash ^= Row.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); @@ -2539,10 +2519,6 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(8); output.WriteEnum((int) Op); } - if (RowPk.Length != 0) { - output.WriteRawTag(18); - output.WriteBytes(RowPk); - } if (Row.Length != 0) { output.WriteRawTag(26); output.WriteBytes(Row); @@ -2561,10 +2537,6 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(8); output.WriteEnum((int) Op); } - if (RowPk.Length != 0) { - output.WriteRawTag(18); - output.WriteBytes(RowPk); - } if (Row.Length != 0) { output.WriteRawTag(26); output.WriteBytes(Row); @@ -2582,9 +2554,6 @@ public int CalculateSize() { if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Op); } - if (RowPk.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(RowPk); - } if (Row.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Row); } @@ -2603,9 +2572,6 @@ public void MergeFrom(TableRowOperation other) { if (other.Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { Op = other.Op; } - if (other.RowPk.Length != 0) { - RowPk = other.RowPk; - } if (other.Row.Length != 0) { Row = other.Row; } @@ -2628,10 +2594,6 @@ public void MergeFrom(pb::CodedInputStream input) { Op = (global::ClientApi.TableRowOperation.Types.OperationType) input.ReadEnum(); break; } - case 18: { - RowPk = input.ReadBytes(); - break; - } case 26: { Row = input.ReadBytes(); break; @@ -2655,10 +2617,6 @@ public void MergeFrom(pb::CodedInputStream input) { Op = (global::ClientApi.TableRowOperation.Types.OperationType) input.ReadEnum(); break; } - case 18: { - RowPk = input.ReadBytes(); - break; - } case 26: { Row = input.ReadBytes(); break; diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index b60a0a705f1..eb761bbcea2 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -127,31 +127,33 @@ public void SetAndForgetDecodedValue(AlgebraicValue value, out object obj) } /// - /// Inserts the value into the table. There can be no existing value with the provided pk. + /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. /// + /// The BSATN encoded bytes of the row to retrieve. + /// The parsed AlgebraicValue of the row encoded by the rowBytes. /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. - public bool InsertEntry(byte[] rowPk, AlgebraicValue value) + public bool InsertEntry(byte[] rowBytes, AlgebraicValue value) { - if (entries.ContainsKey(rowPk)) + if (entries.ContainsKey(rowBytes)) { return false; } // Insert the row into our table - entries[rowPk] = (value, decoderFunc(value)); + entries[rowBytes] = (value, decoderFunc(value)); return true; } /// /// Deletes a value from the table. /// - /// The primary key that uniquely identifies this row - /// - public bool DeleteEntry(byte[] rowPk) + /// The BSATN encoded bytes of the row to remove. + /// True if and only if the value was previously resident and has been deleted. + public bool DeleteEntry(byte[] rowBytes) { - if (entries.TryGetValue(rowPk, out var value)) + if (entries.TryGetValue(rowBytes, out var value)) { - entries.Remove(rowPk); + entries.Remove(rowBytes); return true; } @@ -162,11 +164,12 @@ public bool DeleteEntry(byte[] rowPk) /// /// Gets a value from the table /// - /// The primary key that uniquely identifies this row - /// - public bool TryGetValue(byte[] rowPk, out object value) + /// The BSATN encoded bytes of the row to retrieve. + /// Output: the parsed domain type corresponding to the rowBytes, or null if the row was not present in the cache. + /// True if and only if the value is resident and was stored in value. + public bool TryGetValue(byte[] rowBytes, out object value) { - if (entries.TryGetValue(rowPk, out var v)) + if (entries.TryGetValue(rowBytes, out var v)) { value = v.Item2; return true; diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index dc4f412e4f8..9f819d08a04 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -44,8 +44,8 @@ public struct DbOp public TableOp op; public object newValue; public object oldValue; - public byte[] deletedPk; - public byte[] insertedPk; + public byte[] deletedBytes; + public byte[] insertedBytes; public AlgebraicValue rowValue; public AlgebraicValue primaryKeyValue; } @@ -338,12 +338,11 @@ HashSet GetInsertHashSet(string tableName, int tableSize) foreach (var row in update.TableRowOperations) { - var rowPk = row.RowPk.ToByteArray(); - var rowValue = row.Row.ToByteArray(); + var rowBytes = row.Row.ToByteArray(); stream.Position = 0; - stream.Write(rowValue, 0, rowValue.Length); + stream.Write(rowBytes, 0, rowBytes.Length); stream.Position = 0; - stream.SetLength(rowValue.Length); + stream.SetLength(rowBytes.Length); var deserializedRow = AlgebraicValue.Deserialize(table.RowSchema, reader); if (deserializedRow == null) { @@ -360,8 +359,8 @@ HashSet GetInsertHashSet(string tableName, int tableSize) var op = new DbOp { table = table, - deletedPk = null, - insertedPk = rowPk, + deletedBytes = null, + insertedBytes = rowBytes, op = TableOp.Insert, newValue = obj, oldValue = null, @@ -369,9 +368,9 @@ HashSet GetInsertHashSet(string tableName, int tableSize) rowValue = deserializedRow, }; - if (!hashSet.Add(rowPk)) + if (!hashSet.Add(rowBytes)) { - logger.LogError($"Multiple of the same insert in the same subscription update: table={table.Name} rowPk={rowPk}"); + logger.LogError($"Multiple of the same insert in the same subscription update: table={table.Name} rowBytes={rowBytes}"); } else { @@ -397,12 +396,11 @@ HashSet GetInsertHashSet(string tableName, int tableSize) foreach (var row in update.TableRowOperations) { - var rowPk = row.RowPk.ToByteArray(); - var rowValue = row.Row.ToByteArray(); + var rowBytes = row.Row.ToByteArray(); stream.Position = 0; - stream.Write(rowValue, 0, rowValue.Length); + stream.Write(rowBytes, 0, rowBytes.Length); stream.Position = 0; - stream.SetLength(rowValue.Length); + stream.SetLength(rowBytes.Length); var deserializedRow = AlgebraicValue.Deserialize(table.RowSchema, reader); if (deserializedRow == null) { @@ -416,10 +414,10 @@ HashSet GetInsertHashSet(string tableName, int tableSize) var op = new DbOp { table = table, - deletedPk = - row.Op == TableRowOperation.Types.OperationType.Delete ? rowPk : null, - insertedPk = - row.Op == TableRowOperation.Types.OperationType.Delete ? null : rowPk, + deletedBytes = + row.Op == TableRowOperation.Types.OperationType.Delete ? rowBytes : null, + insertedBytes = + row.Op == TableRowOperation.Types.OperationType.Delete ? null : rowBytes, op = row.Op == TableRowOperation.Types.OperationType.Delete ? TableOp.Delete : TableOp.Insert, @@ -457,8 +455,8 @@ HashSet GetInsertHashSet(string tableName, int tableSize) op = TableOp.Update, newValue = insertOp.newValue, oldValue = deleteOp.oldValue, - deletedPk = deleteOp.deletedPk, - insertedPk = insertOp.insertedPk, + deletedBytes = deleteOp.deletedBytes, + insertedBytes = insertOp.insertedBytes, primaryKeyValue = insertOp.primaryKeyValue, rowValue = insertOp.rowValue, }; @@ -556,14 +554,14 @@ void ExecuteStateDiff() { foreach (var table in clientDB.GetTables()) { - foreach (var rowPk in table.entries.Keys) + foreach (var rowBytes in table.entries.Keys) { if (!preProcessedMessage.inserts.TryGetValue(table.Name, out var hashSet)) { continue; } - if (!hashSet.Contains(rowPk)) + if (!hashSet.Contains(rowBytes)) { // This is a row that we had before, but we do not have it now. // This must have been a delete. @@ -572,9 +570,9 @@ void ExecuteStateDiff() table = table, op = TableOp.Delete, newValue = null, - oldValue = table.entries[rowPk].Item2, - deletedPk = rowPk, - insertedPk = null, + oldValue = table.entries[rowBytes].Item2, + deletedBytes = rowBytes, + insertedBytes = null, primaryKeyValue = null }); } @@ -695,7 +693,7 @@ void InternalInsertCallback(DbOp op) switch (update.op) { case TableOp.Delete: - if (dbOps[i].table.DeleteEntry(update.deletedPk)) + if (dbOps[i].table.DeleteEntry(update.deletedBytes)) { InternalDeleteCallback(update); } @@ -707,7 +705,7 @@ void InternalInsertCallback(DbOp op) } break; case TableOp.Insert: - if (dbOps[i].table.InsertEntry(update.insertedPk, update.rowValue)) + if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) { InternalInsertCallback(update); } @@ -719,7 +717,7 @@ void InternalInsertCallback(DbOp op) } break; case TableOp.Update: - if (dbOps[i].table.DeleteEntry(update.deletedPk)) + if (dbOps[i].table.DeleteEntry(update.deletedBytes)) { InternalDeleteCallback(update); } @@ -730,7 +728,7 @@ void InternalInsertCallback(DbOp op) dbOps[i] = op; } - if (dbOps[i].table.InsertEntry(update.insertedPk, update.rowValue)) + if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) { InternalInsertCallback(update); } From e649c49e80af5d7cad9da09d2437f2a73287281d Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 29 Mar 2024 15:45:52 +0000 Subject: [PATCH 064/223] Add Brotli decompression (#75) C# client counterpart for https://github.com/clockworklabs/SpacetimeDB/pull/1026. --- sdks/csharp/src/SpacetimeDBClient.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 9f819d08a04..8fd17405f2c 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Net.WebSockets; using System.Reflection; @@ -82,7 +83,7 @@ public delegate void RowUpdate(string tableName, TableOp op, object oldValue, ob /// Invoked when a subscription is about to start being processed. This is called even before OnBeforeDelete. /// public event Action onBeforeSubscriptionApplied; - + /// /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. /// @@ -217,7 +218,7 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) var reducerType = FindReducerType(); if (reducerType != null) { - // cache all our reducer events by their function name + // cache all our reducer events by their function name foreach (var methodInfo in reducerType.GetMethods()) { if (methodInfo.GetCustomAttribute() is @@ -286,7 +287,9 @@ void PreProcessMessages() PreProcessedMessage PreProcessMessage(byte[] bytes) { var dbOps = new List(); - var message = Message.Parser.ParseFrom(bytes); + using var compressedStream = new MemoryStream(bytes); + using var decompressedStream = new BrotliStream(compressedStream, CompressionMode.Decompress); + var message = Message.Parser.ParseFrom(decompressedStream); using var stream = new MemoryStream(); using var reader = new BinaryReader(stream); @@ -522,7 +525,7 @@ struct ProcessedMessage } // The message that has been preprocessed and has had its state diff calculated - + private BlockingCollection _stateDiffMessages = new BlockingCollection(); private CancellationTokenSource _stateDiffCancellationTokenSource = new CancellationTokenSource(); private CancellationToken _stateDiffCancellationToken; @@ -560,7 +563,7 @@ void ExecuteStateDiff() { continue; } - + if (!hashSet.Contains(rowBytes)) { // This is a row that we had before, but we do not have it now. @@ -639,7 +642,7 @@ private void OnMessageProcessComplete(Message message, List dbOps) onBeforeSubscriptionApplied?.Invoke(); break; } - + switch (message.TypeCase) { case Message.TypeOneofCase.SubscriptionUpdate: @@ -727,7 +730,7 @@ void InternalInsertCallback(DbOp op) op.op = TableOp.NoChange; dbOps[i] = op; } - + if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) { InternalInsertCallback(update); From 0ca2a5453d3b7df1d10d534fa10a67e384ce32f8 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 23 Apr 2024 13:10:18 +0100 Subject: [PATCH 065/223] Nit: remove unused `inserts` field (#77) --- sdks/csharp/src/SpacetimeDBClient.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 8fd17405f2c..18a24e3ac4f 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -521,7 +521,6 @@ struct ProcessedMessage { public Message message; public List dbOps; - public HashSet inserts; } // The message that has been preprocessed and has had its state diff calculated From f6aa76c7337516e3dbdfb190e337daa6e16e8c6d Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 24 Apr 2024 15:34:17 +0100 Subject: [PATCH 066/223] Set language version to 9 (#80) This is the last C# version supported by Unity. While this PR doesn't require almost any C# code changes, I found that limiting the version is helpful for ensuring that I don't accidentally introduce Unity-incompatible code in larger PRs. --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 3 ++- sdks/csharp/src/AuthToken.cs | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index b47ff21391c..ea112980521 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -2,7 +2,8 @@ net7.0 - enable + 9 + disable enable True SpacetimeDB.ClientSDK diff --git a/sdks/csharp/src/AuthToken.cs b/sdks/csharp/src/AuthToken.cs index 1f5cce339b6..a8a4e7ec0fd 100644 --- a/sdks/csharp/src/AuthToken.cs +++ b/sdks/csharp/src/AuthToken.cs @@ -1,5 +1,5 @@ /* This is an optional helper class to store your auth token in local storage - * + * Example: AuthToken.Init(".my_app_name"); @@ -7,9 +7,9 @@ SpacetimeDBClient.CreateInstance(new ConsoleLogger()); SpacetimeDBClient.instance.onIdentityReceived += (token, identity) => - { + { AuthToken.SaveToken(token); - + ... }; @@ -18,6 +18,7 @@ #if !UNITY_5_3_OR_NEWER using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; @@ -31,7 +32,7 @@ public static class AuthToken /// /// Initializes the AuthToken class. This must be called before any other methods. /// - /// The folder to store the config file in. Default is ".spacetime_csharp_sdk". + /// The folder to store the config file in. Default is ".spacetime_csharp_sdk". /// The name of the config file. Default is "settings.ini". /// The root folder to store the config file in. Default is the user's home directory. /// @@ -67,7 +68,7 @@ public static void Init(string configFolder = ".spacetime_csharp_sdk", string co /// /// This is the auth token that was saved to local storage. Null if not never saved. /// When you specify null to the SpacetimeDBClient, SpacetimeDB will generate a new identity for you. - /// + /// public static string? Token { get @@ -79,7 +80,7 @@ public static string? Token return token; } } - + /// /// Save the auth token to local storage. /// SpacetimeDBClient provides this token to you in the onIdentityReceived callback. @@ -112,4 +113,4 @@ public static void SaveToken(string token) } } } -#endif \ No newline at end of file +#endif From 383ba273241601ff4d908ad95b7228e8f03f1cf0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 24 Apr 2024 17:51:53 +0100 Subject: [PATCH 067/223] Make logger a separate SDK setting from client instance (#79) This allows to: 1. Have a preset logger that is already correctly matching the environment (console vs Unity). 2. Removes the need for explicit `SpacetimeDBClient.CreateInstance(...)` which is particularly awkward to use and easy to forget with singleton as it doesn't return a result as a factory method name could suggest. Instead, `SpacetimeDBClient.instance` is available on first use. 3. Slightly simplifies dependencies between classes, e.g. `ClientCache` doesn't need a circular dependency on `SpacetimeDBClient`, making future maintenance and changes a bit easier. --- sdks/csharp/README.md | 277 +++++++++--------- .../examples/quickstart/client/Program.cs | 5 +- sdks/csharp/src/AuthToken.cs | 2 - sdks/csharp/src/ClientCache.cs | 10 +- sdks/csharp/src/ConsoleLogger.cs | 4 - sdks/csharp/src/ISpacetimeDBLogger.cs | 20 +- sdks/csharp/src/NetworkManager.cs | 10 +- sdks/csharp/src/SpacetimeDBClient.cs | 99 +++---- sdks/csharp/src/UnityDebugLogger.cs | 4 +- sdks/csharp/src/WebSocket.cs | 18 +- 10 files changed, 204 insertions(+), 245 deletions(-) diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 301334ae876..1492cc72c55 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -1,142 +1,135 @@ -# SpacetimeDB SDK for C# - -## Overview - -This repository contains the [C#](https://learn.microsoft.com/en-us/dotnet/csharp/) SDK for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. - -## Documentation - -The C# SDK has a [Quick Start](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-quickstart-guide) guide and a [Reference](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-reference). - -## Installation - -The SDK is available as a [NuGet Package](https://www.nuget.org/packages/SpacetimeDB.ClientSDK). To install it, follow these steps: - -1. Open the NuGet package manager in Visual Studio. -2. Search for `SpacetimeDB.ClientSDK`. -3. Click the install button. - -Alternatively, it can be installed on the command line using the `dotnet` command: - -```bash -dotnet add package SpacetimeDB.ClientSDK -``` - -## Usage - -### Create the SpacetimeDB Client - -To create a SpacetimeDB client, you need to create an instance of the `SpacetimeDBClient` class. The `SpacetimeDBClient` constructor takes the `module_bindings` folder that contains the auto-generated files as a parameter. The `module_bindings` folder is generated by the CLI generate command. - -```csharp -using SpacetimeDB; - -// create the client, pass in a logger to see debug messages -SpacetimeDBClient.CreateInstance(new ConsoleLogger()); -``` - -### Connecting to SpacetimeDB - -To connect to SpacetimeDB, you need to call the `Connect` method on the `SpacetimeDBClient` class. The `Connect` method takes the following parameters: - -- `token`: The authentication token to use to connect to SpacetimeDB. This token is generated by the backend code and is used to authenticate the client. -- `hostName`: The hostname of the SpacetimeDB server. This is the same hostname that you use to connect to the SpacetimeDB web interface. -- `moduleAddress`: The address of the module to connect to. This is the same address that you use to connect to the SpacetimeDB web interface. -- `sslEnabled`: Whether to use SSL to connect to SpacetimeDB. This is the same value that you use to connect to the SpacetimeDB web interface. - -Example: - -```csharp -using SpacetimeDB; - -SpacetimeDBClient.instance.Connect(TOKEN, HOST, DBNAME, SSL_ENABLED); -``` - -### AuthToken optional helper class - -The `AuthToken` class is a helper class that can be used to store the local client's authentication token locally to your user's home directory. - -```csharp -using SpacetimeDB; - -AuthToken.Init(".spacetime_csharp_quickstart"); - -SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME, SSL_ENABLED); - -void OnIdentityReceived(string authToken, Identity identity) -{ - local_identity = identity; - AuthToken.SaveToken(authToken); -} -SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; -``` - -### Subscribing to tables - -To subscribe to a table, you need to call the `Subscribe` method on the `SpacetimeDBClient` class. The `Subscribe` method takes a list of queries as a parameter. The queries are the same queries that you use to subscribe to tables in the SpacetimeDB web interface. - -### Listening to events - -To listen to events, you need to register callbacks on the `SpacetimeDBClient` class. The following callbacks are available: - -- `onConnect`: Called when the client connects to SpacetimeDB. -- `onConnectError`: Called when the client fails to connect to SpacetimeDB. -- `onDisconnect`: Called when the client disconnects from SpacetimeDB. -- `onIdentityReceived`: Called when the client receives its identity from SpacetimeDB. -- `onSubscriptionApplied`: Called when the client receives the initial data from SpacetimeDB after subscribing to tables. - -You can register for row update events on a table. To do this, you need to register callbacks on the table class. The following callbacks are available: - -- `OnInsert`: Called when a row is inserted into the table. -- `OnUpdate`: Called when a row is updated in the table. -- `OnBeforeDelete`: Called before a row is deleted from the table. -- `OnDelete`: Called when a row is deleted from the table. -- `OnRowUpdate`: Called when a row is inserted, updated, or deleted from the table. - -Example: - -```csharp -using SpacetimeDB.Types; - -PlayerComponent.OnInsert += PlayerComponent_OnInsert; -PlayerComponent.OnUpdate += PlayerComponent_OnUpdate; -PlayerComponent.OnDelete += PlayerComponent_OnDelete; -PlayerComponent.OnBeforeDelete += PlayerComponent_OnBeforeDelete; -PlayerComponent.OnRowUpdate += PlayerComponent_OnRowUpdate; -``` - -You can register for reducer call updates as well. - -- `OnREDUCEREvent`: Called when a reducer call is received from SpacetimeDB. (If a) you are subscribed to the table that the reducer modifies or b) You called the reducer and it failed) - -Example: - -```csharp -using SpacetimeDB.Types; - -Reducer.OnMovePlayerEvent += Reducer_OnMovePlayerEvent; -``` - -### Accessing the client cache - -The client cache is a local cache of the data that the client has received from SpacetimeDB. The client cache is automatically updated when the client receives updates from SpacetimeDB. - -When you run the CLI generate command, SpacetimeDB will automatically generate a class for each table in your database. These classes are generated in the `SpacetimeDB.Types` namespace. Each class contains a set of static methods that allow you to query the client cache. The following methods are available: - -- `FilterByCOLUMN`: Filters the table by the specified column value. -- `Iter`: Returns an iterator over the table. -- `Count`: Returns the number of rows in the table. - -### Calling Reducers - -To call a reducer, you need to call the autogenerated method on the `Reducer` class. The autogenerated method takes the reducer arguments as parameters. The reducer arguments are the same arguments that are expected in your server module. - -Example: - -```csharp -using SpacetimeDB.Types; - -Reducer.MovePlayer(new StdbVector2(0.0f, 0.0f), new StdbVector2(1.0f, 1.0f)); -``` - - +# SpacetimeDB SDK for C# + +## Overview + +This repository contains the [C#](https://learn.microsoft.com/en-us/dotnet/csharp/) SDK for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. + +## Documentation + +The C# SDK has a [Quick Start](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-quickstart-guide) guide and a [Reference](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-reference). + +## Installation + +The SDK is available as a [NuGet Package](https://www.nuget.org/packages/SpacetimeDB.ClientSDK). To install it, follow these steps: + +1. Open the NuGet package manager in Visual Studio. +2. Search for `SpacetimeDB.ClientSDK`. +3. Click the install button. + +Alternatively, it can be installed on the command line using the `dotnet` command: + +```bash +dotnet add package SpacetimeDB.ClientSDK +``` + +## Usage + +### Access the SpacetimeDB Client + +The SpacetimeDB client is created automatically as a singleton and accessible via the `SpacetimeDBClient.instance` property. + +### Connecting to SpacetimeDB + +To connect to SpacetimeDB, you need to call the `Connect` method on the `SpacetimeDBClient` class. The `Connect` method takes the following parameters: + +- `token`: The authentication token to use to connect to SpacetimeDB. This token is generated by the backend code and is used to authenticate the client. +- `hostName`: The hostname of the SpacetimeDB server. This is the same hostname that you use to connect to the SpacetimeDB web interface. +- `moduleAddress`: The address of the module to connect to. This is the same address that you use to connect to the SpacetimeDB web interface. +- `sslEnabled`: Whether to use SSL to connect to SpacetimeDB. This is the same value that you use to connect to the SpacetimeDB web interface. + +Example: + +```csharp +using SpacetimeDB; + +SpacetimeDBClient.instance.Connect(TOKEN, HOST, DBNAME, SSL_ENABLED); +``` + +### AuthToken optional helper class + +The `AuthToken` class is a helper class that can be used to store the local client's authentication token locally to your user's home directory. + +```csharp +using SpacetimeDB; + +AuthToken.Init(".spacetime_csharp_quickstart"); + +SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME, SSL_ENABLED); + +void OnIdentityReceived(string authToken, Identity identity) +{ + local_identity = identity; + AuthToken.SaveToken(authToken); +} +SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; +``` + +### Subscribing to tables + +To subscribe to a table, you need to call the `Subscribe` method on the `SpacetimeDBClient` class. The `Subscribe` method takes a list of queries as a parameter. The queries are the same queries that you use to subscribe to tables in the SpacetimeDB web interface. + +### Listening to events + +To listen to events, you need to register callbacks on the `SpacetimeDBClient` class. The following callbacks are available: + +- `onConnect`: Called when the client connects to SpacetimeDB. +- `onConnectError`: Called when the client fails to connect to SpacetimeDB. +- `onDisconnect`: Called when the client disconnects from SpacetimeDB. +- `onIdentityReceived`: Called when the client receives its identity from SpacetimeDB. +- `onSubscriptionApplied`: Called when the client receives the initial data from SpacetimeDB after subscribing to tables. + +You can register for row update events on a table. To do this, you need to register callbacks on the table class. The following callbacks are available: + +- `OnInsert`: Called when a row is inserted into the table. +- `OnUpdate`: Called when a row is updated in the table. +- `OnBeforeDelete`: Called before a row is deleted from the table. +- `OnDelete`: Called when a row is deleted from the table. +- `OnRowUpdate`: Called when a row is inserted, updated, or deleted from the table. + +Example: + +```csharp +using SpacetimeDB.Types; + +PlayerComponent.OnInsert += PlayerComponent_OnInsert; +PlayerComponent.OnUpdate += PlayerComponent_OnUpdate; +PlayerComponent.OnDelete += PlayerComponent_OnDelete; +PlayerComponent.OnBeforeDelete += PlayerComponent_OnBeforeDelete; +PlayerComponent.OnRowUpdate += PlayerComponent_OnRowUpdate; +``` + +You can register for reducer call updates as well. + +- `OnREDUCEREvent`: Called when a reducer call is received from SpacetimeDB. (If a) you are subscribed to the table that the reducer modifies or b) You called the reducer and it failed) + +Example: + +```csharp +using SpacetimeDB.Types; + +Reducer.OnMovePlayerEvent += Reducer_OnMovePlayerEvent; +``` + +### Accessing the client cache + +The client cache is a local cache of the data that the client has received from SpacetimeDB. The client cache is automatically updated when the client receives updates from SpacetimeDB. + +When you run the CLI generate command, SpacetimeDB will automatically generate a class for each table in your database. These classes are generated in the `SpacetimeDB.Types` namespace. Each class contains a set of static methods that allow you to query the client cache. The following methods are available: + +- `FilterByCOLUMN`: Filters the table by the specified column value. +- `Iter`: Returns an iterator over the table. +- `Count`: Returns the number of rows in the table. + +### Calling Reducers + +To call a reducer, you need to call the autogenerated method on the `Reducer` class. The autogenerated method takes the reducer arguments as parameters. The reducer arguments are the same arguments that are expected in your server module. + +Example: + +```csharp +using SpacetimeDB.Types; + +Reducer.MovePlayer(new StdbVector2(0.0f, 0.0f), new StdbVector2(1.0f, 1.0f)); +``` + + diff --git a/sdks/csharp/examples/quickstart/client/Program.cs b/sdks/csharp/examples/quickstart/client/Program.cs index 55074f3becf..9d4a2cc6279 100644 --- a/sdks/csharp/examples/quickstart/client/Program.cs +++ b/sdks/csharp/examples/quickstart/client/Program.cs @@ -13,9 +13,6 @@ void Main() { AuthToken.Init(".spacetime_csharp_quickstart"); - // create the client, pass in a logger to see debug messages - SpacetimeDBClient.CreateInstance(new ConsoleLogger()); - RegisterCallbacks(); // spawn a thread to call process updates and process commands @@ -54,7 +51,7 @@ void User_OnInsert(User insertedValue, ReducerEvent? dbEvent) } } -void User_OnUpdate(User oldValue, User newValue, ReducerEvent dbEvent) +void User_OnUpdate(User oldValue, User newValue, ReducerEvent? dbEvent) { if(oldValue.Name != newValue.Name) { diff --git a/sdks/csharp/src/AuthToken.cs b/sdks/csharp/src/AuthToken.cs index a8a4e7ec0fd..134607c17a5 100644 --- a/sdks/csharp/src/AuthToken.cs +++ b/sdks/csharp/src/AuthToken.cs @@ -4,8 +4,6 @@ AuthToken.Init(".my_app_name"); - SpacetimeDBClient.CreateInstance(new ConsoleLogger()); - SpacetimeDBClient.instance.onIdentityReceived += (token, identity) => { AuthToken.SaveToken(token); diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index eb761bbcea2..e6e8c1e7369 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -138,7 +138,7 @@ public bool InsertEntry(byte[] rowBytes, AlgebraicValue value) { return false; } - + // Insert the row into our table entries[rowBytes] = (value, decoderFunc(value)); return true; @@ -157,7 +157,7 @@ public bool DeleteEntry(byte[] rowBytes) return true; } - SpacetimeDBClient.instance.Logger.LogWarning("Deleting value that we don't have (no cached value available)"); + Logger.LogWarning("Deleting value that we don't have (no cached value available)"); return false; } @@ -204,7 +204,7 @@ public void AddTable(Type clientTableType, AlgebraicType tableRowDef, Func GetTableNames() => tables.Keys; - + public IEnumerable GetTables() => tables.Values; } } diff --git a/sdks/csharp/src/ConsoleLogger.cs b/sdks/csharp/src/ConsoleLogger.cs index 013059aa68d..08f2ce06779 100644 --- a/sdks/csharp/src/ConsoleLogger.cs +++ b/sdks/csharp/src/ConsoleLogger.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace SpacetimeDB { diff --git a/sdks/csharp/src/ISpacetimeDBLogger.cs b/sdks/csharp/src/ISpacetimeDBLogger.cs index 7689e925ccf..33d99cdafef 100644 --- a/sdks/csharp/src/ISpacetimeDBLogger.cs +++ b/sdks/csharp/src/ISpacetimeDBLogger.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace SpacetimeDB { @@ -13,4 +9,20 @@ public interface ISpacetimeDBLogger void LogWarning(string message); void LogException(Exception e); } + + public static class Logger + { + public static ISpacetimeDBLogger Current = + +#if UNITY_5_3_OR_NEWER + new UnityDebugLogger(); +#else + new ConsoleLogger(); +#endif + + public static void Log(string message) => Current.Log(message); + public static void LogError(string message) => Current.LogError(message); + public static void LogWarning(string message) => Current.LogWarning(message); + public static void LogException(Exception e) => Current.LogException(e); + } } diff --git a/sdks/csharp/src/NetworkManager.cs b/sdks/csharp/src/NetworkManager.cs index 8e71b5f22a5..a837cdd65c6 100644 --- a/sdks/csharp/src/NetworkManager.cs +++ b/sdks/csharp/src/NetworkManager.cs @@ -31,12 +31,6 @@ public static string GetTokenKey() public class NetworkManager : MonoBehaviour { - protected void Awake() - { - // If you get a compile error on `Reducer`, that means you need to run the SpacetimeDB CLI generate command - SpacetimeDBClient.CreateInstance(new UnityDebugLogger()); - } - private void OnDestroy() { SpacetimeDBClient.instance.Close(); @@ -45,7 +39,7 @@ private void OnDestroy() private void Update() { SpacetimeDBClient.instance.Update(); - } + } } } -#endif \ No newline at end of file +#endif diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 18a24e3ac4f..6a20ad3a042 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -104,7 +104,7 @@ public delegate void RowUpdate(string tableName, TableOp op, object oldValue, ob /// public event Action onEvent; - public Address clientAddress { get; private set; } + public readonly Address clientAddress = Address.Random(); private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; @@ -123,22 +123,7 @@ public delegate void RowUpdate(string tableName, TableOp op, object oldValue, ob private Thread networkMessageProcessThread; private Thread stateDiffProcessThread; - public static SpacetimeDBClient instance; - - public ISpacetimeDBLogger Logger => logger; - private ISpacetimeDBLogger logger; - - public static void CreateInstance(ISpacetimeDBLogger loggerToUse) - { - if (instance == null) - { - new SpacetimeDBClient(loggerToUse); - } - else - { - loggerToUse.LogError($"Instance already created."); - } - } + public static readonly SpacetimeDBClient instance = new(); public Type FindReducerType() { @@ -165,27 +150,15 @@ public Type FindReducerType() return null; } - protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) + protected SpacetimeDBClient() { - if (instance != null) - { - loggerToUse.LogError($"There is more than one {GetType()}"); - return; - } - - instance = this; - - clientAddress = Address.Random(); - - logger = loggerToUse; - var options = new SpacetimeDB.ConnectOptions { //v1.bin.spacetimedb //v1.text.spacetimedb Protocol = "v1.bin.spacetimedb", }; - webSocket = new SpacetimeDB.WebSocket(logger, options); + webSocket = new SpacetimeDB.WebSocket(options); webSocket.OnMessage += OnMessageReceived; webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); webSocket.OnConnect += () => onConnect?.Invoke(); @@ -239,7 +212,7 @@ protected SpacetimeDBClient(ISpacetimeDBLogger loggerToUse) } else { - loggerToUse.LogError($"Could not find reducer type. Have you run spacetime generate?"); + Logger.LogError($"Could not find reducer type. Have you run spacetime generate?"); } _preProcessCancellationToken = _preProcessCancellationTokenSource.Token; @@ -335,7 +308,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) var table = clientDB.GetTable(tableName); if (table == null) { - logger.LogError($"Unknown table name: {tableName}"); + Logger.LogError($"Unknown table name: {tableName}"); continue; } @@ -354,7 +327,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) if (row.Op != TableRowOperation.Types.OperationType.Insert) { - logger.LogWarning("Non-insert during a subscription update!"); + Logger.LogWarning("Non-insert during a subscription update!"); continue; } @@ -373,7 +346,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) if (!hashSet.Add(rowBytes)) { - logger.LogError($"Multiple of the same insert in the same subscription update: table={table.Name} rowBytes={rowBytes}"); + Logger.LogError($"Multiple of the same insert in the same subscription update: table={table.ClientTableType.Name} rowBytes={rowBytes}"); } else { @@ -393,7 +366,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) var table = clientDB.GetTable(tableName); if (table == null) { - logger.LogError($"Unknown table name: {tableName}"); + Logger.LogError($"Unknown table name: {tableName}"); continue; } @@ -437,7 +410,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) { if (value.op == op.op || value.op == TableOp.Update) { - logger.LogWarning($"Update with the same primary key was " + + Logger.LogWarning($"Update with the same primary key was " + $"applied multiple times! tableName={tableName}"); // TODO(jdetter): Is this a correctable error? This would be a major error on the // SpacetimeDB side. @@ -502,7 +475,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) if (!waitingOneOffQueries.ContainsKey(messageId)) { - logger.LogError("Response to unknown one-off-query: " + messageId); + Logger.LogError("Response to unknown one-off-query: " + messageId); break; } @@ -512,7 +485,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) } - // logger.LogWarning($"Total Updates preprocessed: {totalUpdateCount}"); + // Logger.LogWarning($"Total Updates preprocessed: {totalUpdateCount}"); return new PreProcessedMessage { message = message, dbOps = dbOps, inserts = subscriptionInserts }; } } @@ -613,7 +586,7 @@ public void Connect(string token, string uri, string addressOrName) uri = $"ws://{uri}"; } - logger.Log($"SpacetimeDBClient: Connecting to {uri} {addressOrName}"); + Logger.Log($"SpacetimeDBClient: Connecting to {uri} {addressOrName}"); Task.Run(async () => { try @@ -624,11 +597,11 @@ public void Connect(string token, string uri, string addressOrName) { if (connectionClosed) { - logger.Log("Connection closed gracefully."); + Logger.Log("Connection closed gracefully."); return; } - logger.LogException(e); + Logger.LogException(e); } }); } @@ -658,7 +631,7 @@ private void OnMessageProcessComplete(Message message, List dbOps) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } } } @@ -671,7 +644,7 @@ void InternalDeleteCallback(DbOp op) } else { - logger.LogError("Delete issued, but no value was present!"); + Logger.LogError("Delete issued, but no value was present!"); } } @@ -683,7 +656,7 @@ void InternalInsertCallback(DbOp op) } else { - logger.LogError("Insert issued, but no value was present!"); + Logger.LogError("Insert issued, but no value was present!"); } } @@ -770,7 +743,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } try @@ -783,12 +756,12 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } } else { - logger.LogError("Failed to send callback: invalid insert!"); + Logger.LogError("Failed to send callback: invalid insert!"); } break; @@ -805,7 +778,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } } @@ -818,13 +791,13 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } } } else { - logger.LogError("Failed to send callback: invalid delete"); + Logger.LogError("Failed to send callback: invalid delete"); } break; @@ -843,7 +816,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } try @@ -856,12 +829,12 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } } else { - logger.LogError("Failed to send callback: invalid update"); + Logger.LogError("Failed to send callback: invalid update"); } break; @@ -889,7 +862,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } break; @@ -900,7 +873,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } bool reducerFound = false; @@ -913,7 +886,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } } @@ -927,7 +900,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } } @@ -954,7 +927,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } break; @@ -965,7 +938,7 @@ void InternalInsertCallback(DbOp op) } catch (Exception e) { - logger.LogException(e); + Logger.LogException(e); } break; @@ -978,7 +951,7 @@ public void InternalCallReducer(string json) { if (!webSocket.IsConnected) { - logger.LogError("Cannot call reducer, not connected to server!"); + Logger.LogError("Cannot call reducer, not connected to server!"); return; } @@ -989,7 +962,7 @@ public void Subscribe(List queries) { if (!webSocket.IsConnected) { - logger.LogError("Cannot subscribe, not connected to server!"); + Logger.LogError("Cannot subscribe, not connected to server!"); return; } @@ -1022,7 +995,7 @@ public async Task OneOffQuery(string query) where T : IDatabaseTable T[] LogAndThrow(string error) { error = "While processing one-off-query `" + queryString + "`, ID " + messageId + ": " + error; - logger.LogError(error); + Logger.LogError(error); throw new Exception(error); } diff --git a/sdks/csharp/src/UnityDebugLogger.cs b/sdks/csharp/src/UnityDebugLogger.cs index cc31dd45e79..e78154bd9c9 100644 --- a/sdks/csharp/src/UnityDebugLogger.cs +++ b/sdks/csharp/src/UnityDebugLogger.cs @@ -1,5 +1,5 @@ /* SpacetimeDB logging for Unity - * * This class is only used in Unity projects. + * * This class is only used in Unity projects. * * */ #if UNITY_5_3_OR_NEWER @@ -31,4 +31,4 @@ public void LogWarning(string message) } } } -#endif \ No newline at end of file +#endif diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index b2ffb29521b..203ba029eb5 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -66,8 +66,8 @@ public override void Execute() receiver.Invoke(error, errorMsg); } } - -class OnSendErrorMessage : MainThreadDispatch + + class OnSendErrorMessage : MainThreadDispatch { private WebSocketSendErrorEventHandler receiver; private Exception e; @@ -124,16 +124,12 @@ public class WebSocket // Connection parameters private readonly ConnectOptions _options; private readonly byte[] _receiveBuffer = new byte[MAXMessageSize]; - private readonly ConcurrentQueue dispatchQueue = new ConcurrentQueue(); - - protected ClientWebSocket Ws; + private readonly ConcurrentQueue dispatchQueue = new(); - private ISpacetimeDBLogger _logger; + protected ClientWebSocket Ws = new(); - public WebSocket(ISpacetimeDBLogger logger, ConnectOptions options) + public WebSocket(ConnectOptions options) { - Ws = new ClientWebSocket(); - _logger = logger; _options = options; } @@ -175,13 +171,13 @@ public async Task Connect(string auth, string host, string nameOrAddress, Addres // not a websocket happens when there is no module published under the address specified message = $"{message} Did you forget to publish your module?"; } - _logger.LogException(ex); + Logger.LogException(ex); dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode, message)); return; } catch (Exception e) { - _logger.LogException(e); + Logger.LogException(e); dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, null, e.Message)); return; } From 2fd9eb48eae7350987950bb273c4c9dc83661e48 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 25 Apr 2024 15:43:04 +0100 Subject: [PATCH 068/223] Fix nullability warnings in WebSocket class (#82) There is a bunch of nullability issues in the project; this PR fixes just the ones in WebSocket + some drive-by fixups and/or syntax simplifications. --- sdks/csharp/src/WebSocket.cs | 55 ++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 203ba029eb5..32f1d46e652 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; +using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading; @@ -133,11 +133,11 @@ public WebSocket(ConnectOptions options) _options = options; } - public event WebSocketOpenEventHandler OnConnect; - public event WebSocketConnectErrorEventHandler OnConnectError; - public event WebSocketSendErrorEventHandler OnSendError; - public event WebSocketMessageEventHandler OnMessage; - public event WebSocketCloseEventHandler OnClose; + public event WebSocketOpenEventHandler? OnConnect; + public event WebSocketConnectErrorEventHandler? OnConnectError; + public event WebSocketSendErrorEventHandler? OnSendError; + public event WebSocketMessageEventHandler? OnMessage; + public event WebSocketCloseEventHandler? OnClose; public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } @@ -161,24 +161,24 @@ public async Task Connect(string auth, string host, string nameOrAddress, Addres try { await Ws.ConnectAsync(url, source.Token); - dispatchQueue.Enqueue(new OnConnectMessage(OnConnect)); + if (OnConnect != null) dispatchQueue.Enqueue(new OnConnectMessage(OnConnect)); } catch (WebSocketException ex) { string message = ex.Message; - if(ex.WebSocketErrorCode == WebSocketError.NotAWebSocket) + if (ex.WebSocketErrorCode == WebSocketError.NotAWebSocket) { // not a websocket happens when there is no module published under the address specified message = $"{message} Did you forget to publish your module?"; } Logger.LogException(ex); - dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode, message)); + if (OnConnectError != null) dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode, message)); return; } catch (Exception e) { Logger.LogException(e); - dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, null, e.Message)); + if (OnConnectError != null) dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, null, e.Message)); return; } @@ -195,7 +195,7 @@ public async Task Connect(string auth, string host, string nameOrAddress, Addres await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } - dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, receiveResult.CloseStatus, null)); + if (OnClose != null) dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, receiveResult.CloseStatus, null)); return; } @@ -208,7 +208,7 @@ await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, var closeMessage = $"Maximum message size: {MAXMessageSize} bytes."; await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None); - dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, WebSocketCloseStatus.MessageTooBig, null)); + if (OnClose != null) dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, WebSocketCloseStatus.MessageTooBig, null)); return; } @@ -218,29 +218,25 @@ await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, count += receiveResult.Count; } - var buffCopy = new byte[count]; - for (var x = 0; x < count; x++) - buffCopy[x] = _receiveBuffer[x]; - dispatchQueue.Enqueue(new OnMessage(OnMessage, buffCopy)); + if (OnMessage != null) dispatchQueue.Enqueue(new OnMessage(OnMessage, _receiveBuffer.Take(count).ToArray())); } catch (WebSocketException ex) { - dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, null, ex.WebSocketErrorCode)); + if (OnClose != null) dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, null, ex.WebSocketErrorCode)); return; } } } - public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure, string reason = null) + public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure) { Ws?.CloseAsync(code, "Disconnecting normally.", CancellationToken.None); return Task.CompletedTask; } - private readonly object sendingLock = new object(); - private Task senderTask = null; - private readonly ConcurrentQueue messageSendQueue = new ConcurrentQueue(); + private Task? senderTask; + private readonly ConcurrentQueue messageSendQueue = new(); /// /// This sender guarantees that that messages are sent out in the order they are received. Our websocket @@ -253,10 +249,7 @@ public void Send(byte[] message) lock (messageSendQueue) { messageSendQueue.Enqueue(message); - if (senderTask == null) - { - senderTask = Task.Run(async () => { await ProcessSendQueue(); }); - } + senderTask ??= Task.Run(ProcessSendQueue); } } @@ -267,7 +260,8 @@ private async Task ProcessSendQueue() { while (true) { - byte[] message; + byte[]? message; + lock (messageSendQueue) { if (!messageSendQueue.TryDequeue(out message)) @@ -278,14 +272,13 @@ private async Task ProcessSendQueue() } } - await Ws!.SendAsync(new ArraySegment(message), WebSocketMessageType.Text, true, - CancellationToken.None); + await Ws!.SendAsync(message, WebSocketMessageType.Text, true, CancellationToken.None); } } - catch(Exception e) - { + catch (Exception e) + { senderTask = null; - dispatchQueue.Enqueue(new OnSendErrorMessage(OnSendError, e)); + if (OnSendError != null) dispatchQueue.Enqueue(new OnSendErrorMessage(OnSendError, e)); } } From eaa8fa089461e90a9b4c293b8f60f57c3d2bf92f Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 8 May 2024 10:03:18 -0400 Subject: [PATCH 069/223] Merge ByteArrayComparers (#78) * Merge ByteArrayComparers Merge various mismatched implementation of byte array comparison/hashing into a single utils class (choosing the most efficient implementation already present). * Forward hex conversion too * Use const for Identity & Address sizes --- sdks/csharp/src/Address.cs | 29 +++----------- sdks/csharp/src/ByteArrayConverter.cs | 4 +- sdks/csharp/src/ClientCache.cs | 43 -------------------- sdks/csharp/src/Identity.cs | 27 +++---------- sdks/csharp/src/SpacetimeDBClient.cs | 2 +- sdks/csharp/src/Utils.cs | 58 ++++++++++++++++----------- 6 files changed, 49 insertions(+), 114 deletions(-) diff --git a/sdks/csharp/src/Address.cs b/sdks/csharp/src/Address.cs index 0a0ac37d857..ab18d36b4e0 100644 --- a/sdks/csharp/src/Address.cs +++ b/sdks/csharp/src/Address.cs @@ -11,7 +11,7 @@ public struct Address : IEquatable
    { private byte[] bytes; - public static int SIZE = 16; + public const int SIZE = 16; public byte[] Bytes => bytes; @@ -43,7 +43,7 @@ public static AlgebraicType GetAlgebraicType() public static Address? From(byte[] bytes) { if (bytes.All(b => b == 0)) { - return null; + return null; } return new Address { @@ -51,15 +51,9 @@ public static AlgebraicType GetAlgebraicType() }; } - public bool Equals(Address other) - { - return bytes.SequenceEqual(other.bytes); - } + public bool Equals(Address other) => ByteArrayComparer.Instance.Equals(bytes, other.bytes); - public override bool Equals(object o) - { - return o is Address other && Equals(other); - } + public override bool Equals(object o) => o is Address other && Equals(other); public static bool operator ==(Address a, Address b) => a.Equals(b); public static bool operator !=(Address a, Address b) => !a.Equals(b); @@ -71,19 +65,8 @@ public static Address Random() { return new Address{ bytes = bytes, }; } - public override int GetHashCode() - { - if (bytes == null) - { - throw new InvalidOperationException("Cannot hash on null bytes."); - } - - return BitConverter.ToInt32(bytes, 0); - } + public override int GetHashCode() => ByteArrayComparer.Instance.GetHashCode(bytes); - public override string ToString() - { - return string.Concat(bytes.Select(b => b.ToString("x2"))); - } + public override string ToString() => ByteArrayComparer.ToHexString(bytes); } } diff --git a/sdks/csharp/src/ByteArrayConverter.cs b/sdks/csharp/src/ByteArrayConverter.cs index 6c4bfcd34c9..c60692e5d09 100644 --- a/sdks/csharp/src/ByteArrayConverter.cs +++ b/sdks/csharp/src/ByteArrayConverter.cs @@ -9,7 +9,7 @@ public override bool CanConvert(Type objectType) { return objectType == typeof(byte[]); } - + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); @@ -17,7 +17,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - writer.WriteValue(BitConverter.ToString((byte[])value).Replace("-", string.Empty)); + writer.WriteValue(ByteArrayComparer.ToHexString((byte[])value)); } } } diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index e6e8c1e7369..2e3ae4ef15e 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -12,49 +12,6 @@ public class ClientCache { public class TableCache { - public class ByteArrayComparer : IEqualityComparer - { - public bool Equals(byte[] left, byte[] right) - { - if (ReferenceEquals(left, right)) - { - return true; - } - - if (left == null || right == null || left.Length != right.Length) - { - return false; - } - - return EqualsUnvectorized(left, right); - - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool EqualsUnvectorized(byte[] left, byte[] right) - { - for (int i = 0; i < left.Length; i++) - { - if (left[i] != right[i]) - { - return false; - } - } - - return true; - } - - public int GetHashCode(byte[] obj) - { - int hash = 17; - foreach (byte b in obj) - { - hash = hash * 31 + b; - } - return hash; - } - } - private readonly string name; private readonly Type clientTableType; private readonly AlgebraicType rowSchema; diff --git a/sdks/csharp/src/Identity.cs b/sdks/csharp/src/Identity.cs index 0251a3f931d..1a808eabebb 100644 --- a/sdks/csharp/src/Identity.cs +++ b/sdks/csharp/src/Identity.cs @@ -10,7 +10,7 @@ public struct Identity : IEquatable { private byte[] bytes; - public static int SIZE = 32; + public const int SIZE = 32; public byte[] Bytes => bytes; @@ -48,32 +48,15 @@ public static Identity From(byte[] bytes) }; } - public bool Equals(Identity other) - { - return bytes.SequenceEqual(other.bytes); - } + public bool Equals(Identity other) => ByteArrayComparer.Instance.Equals(bytes, other.bytes); - public override bool Equals(object o) - { - return o is Identity other && Equals(other); - } + public override bool Equals(object o) => o is Identity other && Equals(other); public static bool operator ==(Identity a, Identity b) => a.Equals(b); public static bool operator !=(Identity a, Identity b) => !a.Equals(b); - public override int GetHashCode() - { - if (bytes == null) - { - throw new InvalidOperationException("Cannot hash on null bytes."); - } - - return BitConverter.ToInt32(bytes, 0); - } + public override int GetHashCode() => ByteArrayComparer.Instance.GetHashCode(bytes); - public override string ToString() - { - return string.Concat(bytes.Select(b => b.ToString("x2"))); - } + public override string ToString() => ByteArrayComparer.ToHexString(bytes); } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 6a20ad3a042..024434bbbf1 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -286,7 +286,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) { if (!subscriptionInserts.TryGetValue(tableName, out var hashSet)) { - hashSet = new HashSet(capacity:tableSize, comparer: new ClientCache.TableCache.ByteArrayComparer()); + hashSet = new HashSet(capacity:tableSize, comparer: new ByteArrayComparer()); subscriptionInserts[tableName] = hashSet; } diff --git a/sdks/csharp/src/Utils.cs b/sdks/csharp/src/Utils.cs index 513db490b79..57b4f856dbb 100644 --- a/sdks/csharp/src/Utils.cs +++ b/sdks/csharp/src/Utils.cs @@ -1,44 +1,56 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Runtime.CompilerServices; namespace SpacetimeDB { - public static class Utils + // Note: this utility struct is used by an autogenerated C# code so it needs to be public. + public readonly struct ByteArrayComparer : IEqualityComparer { - public static bool ByteArrayCompare(byte[] a1, byte[] a2) + public static readonly ByteArrayComparer Instance = new(); + + public bool Equals(byte[]? left, byte[]? right) { - if (a1 == null || a2 == null) - return a1 == a2; + if (ReferenceEquals(left, right)) + { + return true; + } - if (a1.Length != a2.Length) + if (left is null || right is null || left.Length != right.Length) + { return false; + } - for (int i = 0; i < a1.Length; i++) - if (a1[i] != a2[i]) - return false; + return EqualsUnvectorized(left, right); - return true; } - } - public class ByteArrayComparer : IEqualityComparer - { - public bool Equals(byte[] x, byte[] y) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool EqualsUnvectorized(byte[] left, byte[] right) { - return Utils.ByteArrayCompare(x, y); + for (int i = 0; i < left.Length; i++) + { + if (left[i] != right[i]) + { + return false; + } + } + + return true; } public int GetHashCode(byte[] obj) { - if (obj == null) - return 0; - int sum = 0; - for (int i = 0; i < obj.Length; i++) - sum += obj[i]; - return sum; + int hash = 17; + foreach (byte b in obj) + { + hash = hash * 31 + b; + } + return hash; } + + // Same as `Convert.ToHexString`, but that method is not available in .NET Standard + // which we need to target for Unity support. + public static string ToHexString(byte[] bytes) => BitConverter.ToString(bytes).Replace("-", ""); } } From 6b5b23d5b8dcb0699cd6dc4a60ca9a60a3fd0fe8 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 9 May 2024 10:47:14 -0400 Subject: [PATCH 070/223] Extract common logic from `OnMessageProcessComplete` (#81) Minor refactoring that extracts common part of subscription and transaction update handling into a separate function, so that the main logic in `OnMessageProcessComplete` is a bit more straightforward and handles all event types with a sinlge `switch` instead of 3 separate `switch`es. This is a small no-op step that makes further refactoring and optimisation of said common logic a bit easier. --- sdks/csharp/src/SpacetimeDBClient.cs | 463 +++++++++++++-------------- 1 file changed, 222 insertions(+), 241 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 024434bbbf1..0f191de1f32 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -286,7 +286,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) { if (!subscriptionInserts.TryGetValue(tableName, out var hashSet)) { - hashSet = new HashSet(capacity:tableSize, comparer: new ByteArrayComparer()); + hashSet = new HashSet(capacity: tableSize, comparer: new ByteArrayComparer()); subscriptionInserts[tableName] = hashSet; } @@ -606,315 +606,296 @@ public void Connect(string token, string uri, string addressOrName) }); } - private void OnMessageProcessComplete(Message message, List dbOps) + private void OnMessageProcessCompleteUpdate(Message message, List dbOps) { - switch (message.TypeCase) + // First trigger OnBeforeDelete + foreach (var update in dbOps) { - case Message.TypeOneofCase.SubscriptionUpdate: - onBeforeSubscriptionApplied?.Invoke(); - break; + if (update.op == TableOp.Delete) + { + try + { + update.table.BeforeDeleteCallback?.Invoke(update.oldValue, + message.TransactionUpdate?.Event); + } + catch (Exception e) + { + Logger.LogException(e); + } + } } - switch (message.TypeCase) + void InternalDeleteCallback(DbOp op) { - case Message.TypeOneofCase.SubscriptionUpdate: - case Message.TypeOneofCase.TransactionUpdate: - // First trigger OnBeforeDelete - foreach (var update in dbOps) - { - if (update.op == TableOp.Delete) + if (op.oldValue != null) + { + op.table.InternalValueDeletedCallback(op.oldValue); + } + else + { + Logger.LogError("Delete issued, but no value was present!"); + } + } + + void InternalInsertCallback(DbOp op) + { + if (op.newValue != null) + { + op.table.InternalValueInsertedCallback(op.newValue); + } + else + { + Logger.LogError("Insert issued, but no value was present!"); + } + } + + // Apply all of the state + for (var i = 0; i < dbOps.Count; i++) + { + // TODO: Reimplement updates when we add support for primary keys + var update = dbOps[i]; + switch (update.op) + { + case TableOp.Delete: + if (dbOps[i].table.DeleteEntry(update.deletedBytes)) { - try - { - update.table.BeforeDeleteCallback?.Invoke(update.oldValue, - message.TransactionUpdate?.Event); - } - catch (Exception e) - { - Logger.LogException(e); - } + InternalDeleteCallback(update); } - } - - void InternalDeleteCallback(DbOp op) - { - if (op.oldValue != null) + else { - op.table.InternalValueDeletedCallback(op.oldValue); + var op = dbOps[i]; + op.op = TableOp.NoChange; + dbOps[i] = op; + } + break; + case TableOp.Insert: + if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) + { + InternalInsertCallback(update); } else { - Logger.LogError("Delete issued, but no value was present!"); + var op = dbOps[i]; + op.op = TableOp.NoChange; + dbOps[i] = op; + } + break; + case TableOp.Update: + if (dbOps[i].table.DeleteEntry(update.deletedBytes)) + { + InternalDeleteCallback(update); + } + else + { + var op = dbOps[i]; + op.op = TableOp.NoChange; + dbOps[i] = op; } - } - void InternalInsertCallback(DbOp op) - { - if (op.newValue != null) + if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) { - op.table.InternalValueInsertedCallback(op.newValue); + InternalInsertCallback(update); } else { - Logger.LogError("Insert issued, but no value was present!"); + var op = dbOps[i]; + op.op = TableOp.NoChange; + dbOps[i] = op; } - } + break; + default: + throw new ArgumentOutOfRangeException(); + } + } - // Apply all of the state - for (var i = 0; i < dbOps.Count; i++) - { - // TODO: Reimplement updates when we add support for primary keys - var update = dbOps[i]; - switch (update.op) + // Send out events + var updateCount = dbOps.Count; + for (var i = 0; i < updateCount; i++) + { + var tableName = dbOps[i].table.ClientTableType.Name; + var tableOp = dbOps[i].op; + var oldValue = dbOps[i].oldValue; + var newValue = dbOps[i].newValue; + + switch (tableOp) + { + case TableOp.Insert: + if (oldValue == null && newValue != null) { - case TableOp.Delete: - if (dbOps[i].table.DeleteEntry(update.deletedBytes)) - { - InternalDeleteCallback(update); - } - else - { - var op = dbOps[i]; - op.op = TableOp.NoChange; - dbOps[i] = op; - } - break; - case TableOp.Insert: - if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) - { - InternalInsertCallback(update); - } - else - { - var op = dbOps[i]; - op.op = TableOp.NoChange; - dbOps[i] = op; - } - break; - case TableOp.Update: - if (dbOps[i].table.DeleteEntry(update.deletedBytes)) - { - InternalDeleteCallback(update); - } - else + try + { + if (dbOps[i].table.InsertCallback != null) { - var op = dbOps[i]; - op.op = TableOp.NoChange; - dbOps[i] = op; + dbOps[i].table.InsertCallback.Invoke(newValue, + message.TransactionUpdate?.Event); } + } + catch (Exception e) + { + Logger.LogException(e); + } - if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) - { - InternalInsertCallback(update); - } - else + try + { + if (dbOps[i].table.RowUpdatedCallback != null) { - var op = dbOps[i]; - op.op = TableOp.NoChange; - dbOps[i] = op; + dbOps[i].table.RowUpdatedCallback + .Invoke(tableOp, null, newValue, message.TransactionUpdate?.Event); } - break; - default: - throw new ArgumentOutOfRangeException(); + } + catch (Exception e) + { + Logger.LogException(e); + } + } + else + { + Logger.LogError("Failed to send callback: invalid insert!"); } - } - - // Send out events - var updateCount = dbOps.Count; - for (var i = 0; i < updateCount; i++) - { - var tableName = dbOps[i].table.ClientTableType.Name; - var tableOp = dbOps[i].op; - var oldValue = dbOps[i].oldValue; - var newValue = dbOps[i].newValue; - switch (tableOp) + break; + case TableOp.Delete: { - case TableOp.Insert: - if (oldValue == null && newValue != null) + if (oldValue != null && newValue == null) + { + if (dbOps[i].table.DeleteCallback != null) { try { - if (dbOps[i].table.InsertCallback != null) - { - dbOps[i].table.InsertCallback.Invoke(newValue, - message.TransactionUpdate?.Event); - } + dbOps[i].table.DeleteCallback.Invoke(oldValue, + message.TransactionUpdate?.Event); } catch (Exception e) { Logger.LogException(e); } + } + if (dbOps[i].table.RowUpdatedCallback != null) + { try { - if (dbOps[i].table.RowUpdatedCallback != null) - { - dbOps[i].table.RowUpdatedCallback - .Invoke(tableOp, null, newValue, message.TransactionUpdate?.Event); - } + dbOps[i].table.RowUpdatedCallback + .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); } catch (Exception e) { Logger.LogException(e); } } - else - { - Logger.LogError("Failed to send callback: invalid insert!"); - } - - break; - case TableOp.Delete: - { - if (oldValue != null && newValue == null) - { - if (dbOps[i].table.DeleteCallback != null) - { - try - { - dbOps[i].table.DeleteCallback.Invoke(oldValue, - message.TransactionUpdate?.Event); - } - catch (Exception e) - { - Logger.LogException(e); - } - } - - if (dbOps[i].table.RowUpdatedCallback != null) - { - try - { - dbOps[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); - } - catch (Exception e) - { - Logger.LogException(e); - } - } - } - else - { - Logger.LogError("Failed to send callback: invalid delete"); - } - - break; - } - case TableOp.Update: - { - if (oldValue != null && newValue != null) - { - try - { - if (dbOps[i].table.UpdateCallback != null) - { - dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, - message.TransactionUpdate?.Event); - } - } - catch (Exception e) - { - Logger.LogException(e); - } - - try - { - if (dbOps[i].table.RowUpdatedCallback != null) - { - dbOps[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, newValue, message.TransactionUpdate?.Event); - } - } - catch (Exception e) - { - Logger.LogException(e); - } - } - else - { - Logger.LogError("Failed to send callback: invalid update"); - } - - break; - } - case TableOp.NoChange: - // noop - break; - default: - throw new ArgumentOutOfRangeException(); - } - - if (tableOp != TableOp.NoChange) - { - onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue, - message.Event?.FunctionCall.CallInfo); - } - } - - switch (message.TypeCase) - { - case Message.TypeOneofCase.SubscriptionUpdate: - try - { - onSubscriptionApplied?.Invoke(); } - catch (Exception e) + else { - Logger.LogException(e); + Logger.LogError("Failed to send callback: invalid delete"); } break; - case Message.TypeOneofCase.TransactionUpdate: - try - { - onEvent?.Invoke(message.TransactionUpdate.Event); - } - catch (Exception e) - { - Logger.LogException(e); - } - - bool reducerFound = false; - var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; - if (reducerEventCache.TryGetValue(functionName, out var value)) + } + case TableOp.Update: + { + if (oldValue != null && newValue != null) { try { - reducerFound = value.Invoke(message.TransactionUpdate.Event); + if (dbOps[i].table.UpdateCallback != null) + { + dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, + message.TransactionUpdate?.Event); + } } catch (Exception e) { Logger.LogException(e); } - } - if (!reducerFound && message.TransactionUpdate.Event.Status == - ClientApi.Event.Types.Status.Failed) - { try { - onUnhandledReducerError?.Invoke(message.TransactionUpdate.Event.FunctionCall - .CallInfo); + if (dbOps[i].table.RowUpdatedCallback != null) + { + dbOps[i].table.RowUpdatedCallback + .Invoke(tableOp, oldValue, newValue, message.TransactionUpdate?.Event); + } } catch (Exception e) { Logger.LogException(e); } } + else + { + Logger.LogError("Failed to send callback: invalid update"); + } break; - case Message.TypeOneofCase.None: - break; - case Message.TypeOneofCase.FunctionCall: - break; - case Message.TypeOneofCase.Event: - break; - case Message.TypeOneofCase.IdentityToken: - break; - default: - throw new ArgumentOutOfRangeException(); + } + case TableOp.NoChange: + // noop + break; + default: + throw new ArgumentOutOfRangeException(); + } + + if (tableOp != TableOp.NoChange) + { + onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue, + message.Event?.FunctionCall.CallInfo); + } + } + } + + private void OnMessageProcessComplete(Message message, List dbOps) + { + switch (message.TypeCase) + { + case Message.TypeOneofCase.SubscriptionUpdate: + onBeforeSubscriptionApplied?.Invoke(); + OnMessageProcessCompleteUpdate(message, dbOps); + try + { + onSubscriptionApplied?.Invoke(); + } + catch (Exception e) + { + Logger.LogException(e); + } + break; + case Message.TypeOneofCase.TransactionUpdate: + OnMessageProcessCompleteUpdate(message, dbOps); + try + { + onEvent?.Invoke(message.TransactionUpdate.Event); + } + catch (Exception e) + { + Logger.LogException(e); + } + + bool reducerFound = false; + var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; + if (reducerEventCache.TryGetValue(functionName, out var value)) + { + try + { + reducerFound = value.Invoke(message.TransactionUpdate.Event); + } + catch (Exception e) + { + Logger.LogException(e); + } + } + + if (!reducerFound && message.TransactionUpdate.Event.Status == + ClientApi.Event.Types.Status.Failed) + { + try + { + onUnhandledReducerError?.Invoke(message.TransactionUpdate.Event.FunctionCall + .CallInfo); + } + catch (Exception e) + { + Logger.LogException(e); + } } break; From ce38cd100bd58e96872ee4bed9aa90c90e1b7597 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 9 May 2024 19:18:18 -0400 Subject: [PATCH 071/223] NFC: remove unused primaryKeyValue field (#85) This field is only used in self-assignment, so can be safely removed. --- sdks/csharp/src/SpacetimeDBClient.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 0f191de1f32..9db878c304c 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -48,7 +48,6 @@ public struct DbOp public byte[] deletedBytes; public byte[] insertedBytes; public AlgebraicValue rowValue; - public AlgebraicValue primaryKeyValue; } public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, @@ -340,7 +339,6 @@ HashSet GetInsertHashSet(string tableName, int tableSize) op = TableOp.Insert, newValue = obj, oldValue = null, - primaryKeyValue = null, rowValue = deserializedRow, }; @@ -399,7 +397,6 @@ HashSet GetInsertHashSet(string tableName, int tableSize) : TableOp.Insert, newValue = row.Op == TableRowOperation.Types.OperationType.Delete ? null : obj, oldValue = row.Op == TableRowOperation.Types.OperationType.Delete ? obj : null, - primaryKeyValue = primaryKeyValue, rowValue = deserializedRow, }; @@ -433,7 +430,6 @@ HashSet GetInsertHashSet(string tableName, int tableSize) oldValue = deleteOp.oldValue, deletedBytes = deleteOp.deletedBytes, insertedBytes = insertOp.insertedBytes, - primaryKeyValue = insertOp.primaryKeyValue, rowValue = insertOp.rowValue, }; } @@ -547,8 +543,7 @@ void ExecuteStateDiff() newValue = null, oldValue = table.entries[rowBytes].Item2, deletedBytes = rowBytes, - insertedBytes = null, - primaryKeyValue = null + insertedBytes = null }); } } From 1bb67c59a96198ffb6d3d51a147628ade50681c2 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 10 May 2024 17:41:23 -0400 Subject: [PATCH 072/223] Remove RowUpdate event (#83) We talked about this for a while, so decided to do this in a separate PR. --- sdks/csharp/README.md | 4 - sdks/csharp/src/ClientCache.cs | 4 - sdks/csharp/src/SpacetimeDBClient.cs | 164 +++++++++------------------ 3 files changed, 55 insertions(+), 117 deletions(-) diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 1492cc72c55..44e63351088 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -84,7 +84,6 @@ You can register for row update events on a table. To do this, you need to regis - `OnUpdate`: Called when a row is updated in the table. - `OnBeforeDelete`: Called before a row is deleted from the table. - `OnDelete`: Called when a row is deleted from the table. -- `OnRowUpdate`: Called when a row is inserted, updated, or deleted from the table. Example: @@ -95,7 +94,6 @@ PlayerComponent.OnInsert += PlayerComponent_OnInsert; PlayerComponent.OnUpdate += PlayerComponent_OnUpdate; PlayerComponent.OnDelete += PlayerComponent_OnDelete; PlayerComponent.OnBeforeDelete += PlayerComponent_OnBeforeDelete; -PlayerComponent.OnRowUpdate += PlayerComponent_OnRowUpdate; ``` You can register for reducer call updates as well. @@ -131,5 +129,3 @@ using SpacetimeDB.Types; Reducer.MovePlayer(new StdbVector2(0.0f, 0.0f), new StdbVector2(1.0f, 1.0f)); ``` - - diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 2e3ae4ef15e..93f82577e64 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -33,8 +33,6 @@ public Type ClientTableType public Action BeforeDeleteCallback; public Action DeleteCallback; public Action UpdateCallback; - // TODO: Consider renaming this one, this kind of implies that its a callback for the Update operation - public Action RowUpdatedCallback; public Func ComparePrimaryKeyFunc; public Func GetPrimaryKeyValueFunc; public Func GetPrimaryKeyTypeFunc; @@ -62,8 +60,6 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func)clientTableType.GetMethod("OnBeforeDeleteEvent")?.CreateDelegate(typeof(Action)); DeleteCallback = (Action)clientTableType.GetMethod("OnDeleteEvent")?.CreateDelegate(typeof(Action)); UpdateCallback = (Action)clientTableType.GetMethod("OnUpdateEvent")?.CreateDelegate(typeof(Action)); - RowUpdatedCallback = (Action)clientTableType.GetMethod("OnRowUpdateEvent") - ?.CreateDelegate(typeof(Action)); ComparePrimaryKeyFunc = (Func)clientTableType.GetMethod("ComparePrimaryKey", BindingFlags.Static | BindingFlags.Public) ?.CreateDelegate(typeof(Func)); GetPrimaryKeyValueFunc = (Func)clientTableType.GetMethod("GetPrimaryKeyValue", BindingFlags.Static | BindingFlags.Public) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 9db878c304c..9c1263dab7f 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -50,9 +50,6 @@ public struct DbOp public AlgebraicValue rowValue; } - public delegate void RowUpdate(string tableName, TableOp op, object oldValue, object newValue, - SpacetimeDB.ReducerEventBase dbEvent); - /// /// Called when a connection is established to a spacetimedb instance. /// @@ -73,11 +70,6 @@ public delegate void RowUpdate(string tableName, TableOp op, object oldValue, ob ///
    public event Action onDisconnect; - /// - /// Invoked on each row update to each table. - /// - public event RowUpdate onRowUpdate; - /// /// Invoked when a subscription is about to start being processed. This is called even before OnBeforeDelete. /// @@ -712,131 +704,85 @@ void InternalInsertCallback(DbOp op) var oldValue = dbOps[i].oldValue; var newValue = dbOps[i].newValue; - switch (tableOp) - { - case TableOp.Insert: - if (oldValue == null && newValue != null) + switch (tableOp) { - try - { - if (dbOps[i].table.InsertCallback != null) - { - dbOps[i].table.InsertCallback.Invoke(newValue, - message.TransactionUpdate?.Event); - } - } - catch (Exception e) - { - Logger.LogException(e); - } - - try - { - if (dbOps[i].table.RowUpdatedCallback != null) - { - dbOps[i].table.RowUpdatedCallback - .Invoke(tableOp, null, newValue, message.TransactionUpdate?.Event); - } - } - catch (Exception e) - { - Logger.LogException(e); - } - } - else - { - Logger.LogError("Failed to send callback: invalid insert!"); - } - - break; - case TableOp.Delete: - { - if (oldValue != null && newValue == null) - { - if (dbOps[i].table.DeleteCallback != null) + case TableOp.Insert: + if (oldValue == null && newValue != null) { try { - dbOps[i].table.DeleteCallback.Invoke(oldValue, - message.TransactionUpdate?.Event); + if (dbOps[i].table.InsertCallback != null) + { + dbOps[i].table.InsertCallback.Invoke(newValue, + message.TransactionUpdate?.Event); + } } catch (Exception e) { Logger.LogException(e); } } + else + { + Logger.LogError("Failed to send callback: invalid insert!"); + } - if (dbOps[i].table.RowUpdatedCallback != null) + break; + case TableOp.Delete: { - try + if (oldValue != null && newValue == null) { - dbOps[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, null, message.TransactionUpdate?.Event); + if (dbOps[i].table.DeleteCallback != null) + { + try + { + dbOps[i].table.DeleteCallback.Invoke(oldValue, + message.TransactionUpdate?.Event); + } + catch (Exception e) + { + Logger.LogException(e); + } + } } - catch (Exception e) + else { - Logger.LogException(e); + Logger.LogError("Failed to send callback: invalid delete"); } - } - } - else - { - Logger.LogError("Failed to send callback: invalid delete"); - } - break; - } - case TableOp.Update: - { - if (oldValue != null && newValue != null) - { - try + break; + } + case TableOp.Update: { - if (dbOps[i].table.UpdateCallback != null) + if (oldValue != null && newValue != null) { - dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, - message.TransactionUpdate?.Event); + try + { + if (dbOps[i].table.UpdateCallback != null) + { + dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, + message.TransactionUpdate?.Event); + } + } + catch (Exception e) + { + Logger.LogException(e); + } } - } - catch (Exception e) - { - Logger.LogException(e); - } - - try - { - if (dbOps[i].table.RowUpdatedCallback != null) + else { - dbOps[i].table.RowUpdatedCallback - .Invoke(tableOp, oldValue, newValue, message.TransactionUpdate?.Event); + Logger.LogError("Failed to send callback: invalid update"); } - } - catch (Exception e) - { - Logger.LogException(e); - } - } - else - { - Logger.LogError("Failed to send callback: invalid update"); - } - break; + break; + } + case TableOp.NoChange: + // noop + break; + default: + throw new ArgumentOutOfRangeException(); } - case TableOp.NoChange: - // noop - break; - default: - throw new ArgumentOutOfRangeException(); - } - - if (tableOp != TableOp.NoChange) - { - onRowUpdate?.Invoke(tableName, tableOp, oldValue, newValue, - message.Event?.FunctionCall.CallInfo); - } - } - } + } private void OnMessageProcessComplete(Message message, List dbOps) { From c925af1791a2025d0b0a6e43f00ed3b20112b7d6 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 13 May 2024 11:45:56 -0400 Subject: [PATCH 073/223] Fix conflict resolution shenanigans (#87) --- .../client/module_bindings/Message.cs | 7 - .../quickstart/client/module_bindings/User.cs | 7 - sdks/csharp/src/SpacetimeDBClient.cs | 123 +++++++++--------- 3 files changed, 62 insertions(+), 75 deletions(-) diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs index 25800e8f19a..438777e8545 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs @@ -109,11 +109,9 @@ public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, Spacetime public delegate void InsertEventHandler(Message insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void DeleteEventHandler(Message deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); - public delegate void RowUpdateEventHandler(SpacetimeDBClient.TableOp op, Message oldValue, Message newValue, SpacetimeDB.Types.ReducerEvent dbEvent); public static event InsertEventHandler OnInsert; public static event DeleteEventHandler OnBeforeDelete; public static event DeleteEventHandler OnDelete; - public static event RowUpdateEventHandler OnRowUpdate; public static void OnInsertEvent(object newValue, ClientApi.Event dbEvent) { @@ -129,10 +127,5 @@ public static void OnDeleteEvent(object oldValue, ClientApi.Event dbEvent) { OnDelete?.Invoke((Message)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); } - - public static void OnRowUpdateEvent(SpacetimeDBClient.TableOp op, object oldValue, object newValue, ClientApi.Event dbEvent) - { - OnRowUpdate?.Invoke(op, (Message)oldValue,(Message)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } } } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs index 85c7ca12b7d..04230fc3e67 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs @@ -126,12 +126,10 @@ public static SpacetimeDB.SATS.AlgebraicType GetPrimaryKeyType(SpacetimeDB.SATS. public delegate void InsertEventHandler(User insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void UpdateEventHandler(User oldValue, User newValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void DeleteEventHandler(User deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); - public delegate void RowUpdateEventHandler(SpacetimeDBClient.TableOp op, User oldValue, User newValue, SpacetimeDB.Types.ReducerEvent dbEvent); public static event InsertEventHandler OnInsert; public static event UpdateEventHandler OnUpdate; public static event DeleteEventHandler OnBeforeDelete; public static event DeleteEventHandler OnDelete; - public static event RowUpdateEventHandler OnRowUpdate; public static void OnInsertEvent(object newValue, ClientApi.Event dbEvent) { @@ -152,10 +150,5 @@ public static void OnDeleteEvent(object oldValue, ClientApi.Event dbEvent) { OnDelete?.Invoke((User)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); } - - public static void OnRowUpdateEvent(SpacetimeDBClient.TableOp op, object oldValue, object newValue, ClientApi.Event dbEvent) - { - OnRowUpdate?.Invoke(op, (User)oldValue,(User)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 9c1263dab7f..bddc4e6c2f5 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -704,85 +704,86 @@ void InternalInsertCallback(DbOp op) var oldValue = dbOps[i].oldValue; var newValue = dbOps[i].newValue; - switch (tableOp) + switch (tableOp) + { + case TableOp.Insert: + if (oldValue == null && newValue != null) { - case TableOp.Insert: - if (oldValue == null && newValue != null) + try + { + if (dbOps[i].table.InsertCallback != null) + { + dbOps[i].table.InsertCallback.Invoke(newValue, + message.TransactionUpdate?.Event); + } + } + catch (Exception e) + { + Logger.LogException(e); + } + } + else + { + Logger.LogError("Failed to send callback: invalid insert!"); + } + + break; + case TableOp.Delete: + { + if (oldValue != null && newValue == null) + { + if (dbOps[i].table.DeleteCallback != null) { try { - if (dbOps[i].table.InsertCallback != null) - { - dbOps[i].table.InsertCallback.Invoke(newValue, - message.TransactionUpdate?.Event); - } + dbOps[i].table.DeleteCallback.Invoke(oldValue, + message.TransactionUpdate?.Event); } catch (Exception e) { Logger.LogException(e); } } - else - { - Logger.LogError("Failed to send callback: invalid insert!"); - } + } + else + { + Logger.LogError("Failed to send callback: invalid delete"); + } - break; - case TableOp.Delete: + break; + } + case TableOp.Update: + { + if (oldValue != null && newValue != null) + { + try { - if (oldValue != null && newValue == null) - { - if (dbOps[i].table.DeleteCallback != null) - { - try - { - dbOps[i].table.DeleteCallback.Invoke(oldValue, - message.TransactionUpdate?.Event); - } - catch (Exception e) - { - Logger.LogException(e); - } - } - } - else + if (dbOps[i].table.UpdateCallback != null) { - Logger.LogError("Failed to send callback: invalid delete"); + dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, + message.TransactionUpdate?.Event); } - - break; } - case TableOp.Update: + catch (Exception e) { - if (oldValue != null && newValue != null) - { - try - { - if (dbOps[i].table.UpdateCallback != null) - { - dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, - message.TransactionUpdate?.Event); - } - } - catch (Exception e) - { - Logger.LogException(e); - } - } - else - { - Logger.LogError("Failed to send callback: invalid update"); - } - - break; + Logger.LogException(e); } - case TableOp.NoChange: - // noop - break; - default: - throw new ArgumentOutOfRangeException(); + } + else + { + Logger.LogError("Failed to send callback: invalid update"); + } + + break; } - } + case TableOp.NoChange: + // noop + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + } private void OnMessageProcessComplete(Message message, List dbOps) { From 8ca04842c5f80bea8cda7d308e9ec9236ae7c610 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 13 May 2024 11:49:57 -0400 Subject: [PATCH 074/223] Add basic CI (#88) --- sdks/csharp/.github/workflows/dotnet.yml | 21 +++++++++++++++++++ .../examples/quickstart/client/client.sln | 6 ++++++ 2 files changed, 27 insertions(+) create mode 100644 sdks/csharp/.github/workflows/dotnet.yml diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml new file mode 100644 index 00000000000..74bfc91e80e --- /dev/null +++ b/sdks/csharp/.github/workflows/dotnet.yml @@ -0,0 +1,21 @@ +# This workflow will build a .NET project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net + +name: .NET build + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 7.0.x + - name: Build client example + run: dotnet build + working-directory: examples/quickstart/client diff --git a/sdks/csharp/examples/quickstart/client/client.sln b/sdks/csharp/examples/quickstart/client/client.sln index f77ec29b6c8..524c0df2b82 100644 --- a/sdks/csharp/examples/quickstart/client/client.sln +++ b/sdks/csharp/examples/quickstart/client/client.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 17.6.33717.318 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "client.csproj", "{8F33709C-DEE9-41CC-A477-D6128E3700B1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpacetimeDB.ClientSDK", "..\..\..\SpacetimeDB.ClientSDK.csproj", "{242A8146-A58D-43E9-A2BD-31FFC6851AA6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.Build.0 = Debug|Any CPU {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.ActiveCfg = Release|Any CPU {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.Build.0 = Release|Any CPU + {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From c8319ebb98fec908fc08f82396cdf269f3011fc1 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 13 May 2024 12:05:43 -0400 Subject: [PATCH 075/223] Simplify event dispatch in WebSocket (#90) ## Description of Changes Instead of using custom class hierarchy of messages, we can just use native C# lambdas stored as Actions. OnConnectError case can be further simplified by merging two branches for different exception types into one. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/WebSocket.cs | 137 ++++++----------------------------- 1 file changed, 23 insertions(+), 114 deletions(-) diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 32f1d46e652..4dcd8a34b08 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -8,99 +8,6 @@ namespace SpacetimeDB { - internal abstract class MainThreadDispatch - { - public abstract void Execute(); - } - - class OnConnectMessage : MainThreadDispatch - { - private WebSocketOpenEventHandler receiver; - - public OnConnectMessage(WebSocketOpenEventHandler receiver) - { - this.receiver = receiver; - } - - public override void Execute() - { - receiver.Invoke(); - } - } - - class OnDisconnectMessage : MainThreadDispatch - { - private WebSocketCloseEventHandler receiver; - private WebSocketError? error; - private WebSocketCloseStatus? status; - - public OnDisconnectMessage(WebSocketCloseEventHandler receiver, WebSocketCloseStatus? status, - WebSocketError? error) - { - this.receiver = receiver; - this.error = error; - this.status = status; - } - - public override void Execute() - { - receiver.Invoke(status, error); - } - } - - class OnConnectErrorMessage : MainThreadDispatch - { - private WebSocketConnectErrorEventHandler receiver; - private WebSocketError? error; - private string? errorMsg; - - public OnConnectErrorMessage(WebSocketConnectErrorEventHandler receiver, WebSocketError? error, string? errorMsg) - { - this.receiver = receiver; - this.error = error; - this.errorMsg = errorMsg; - } - - public override void Execute() - { - receiver.Invoke(error, errorMsg); - } - } - - class OnSendErrorMessage : MainThreadDispatch - { - private WebSocketSendErrorEventHandler receiver; - private Exception e; - - public OnSendErrorMessage(WebSocketSendErrorEventHandler receiver, Exception e) - { - this.receiver = receiver; - this.e = e; - } - - public override void Execute() - { - receiver.Invoke(e); - } - } - - class OnMessage : MainThreadDispatch - { - private WebSocketMessageEventHandler receiver; - private byte[] message; - - public OnMessage(WebSocketMessageEventHandler receiver, byte[] message) - { - this.receiver = receiver; - this.message = message; - } - - public override void Execute() - { - receiver.Invoke(message); - } - } - public delegate void WebSocketOpenEventHandler(); public delegate void WebSocketMessageEventHandler(byte[] message); @@ -124,7 +31,7 @@ public class WebSocket // Connection parameters private readonly ConnectOptions _options; private readonly byte[] _receiveBuffer = new byte[MAXMessageSize]; - private readonly ConcurrentQueue dispatchQueue = new(); + private readonly ConcurrentQueue dispatchQueue = new(); protected ClientWebSocket Ws = new(); @@ -161,24 +68,22 @@ public async Task Connect(string auth, string host, string nameOrAddress, Addres try { await Ws.ConnectAsync(url, source.Token); - if (OnConnect != null) dispatchQueue.Enqueue(new OnConnectMessage(OnConnect)); + if (OnConnect != null) dispatchQueue.Enqueue(() => OnConnect()); } - catch (WebSocketException ex) + catch (Exception ex) { - string message = ex.Message; - if (ex.WebSocketErrorCode == WebSocketError.NotAWebSocket) + Logger.LogException(ex); + if (OnConnectError != null) { - // not a websocket happens when there is no module published under the address specified - message = $"{message} Did you forget to publish your module?"; + var message = ex.Message; + var code = (ex as WebSocketException)?.WebSocketErrorCode; + if (code == WebSocketError.NotAWebSocket) + { + // not a websocket happens when there is no module published under the address specified + message += " Did you forget to publish your module?"; + } + dispatchQueue.Enqueue(() => OnConnectError(code, message)); } - Logger.LogException(ex); - if (OnConnectError != null) dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, ex.WebSocketErrorCode, message)); - return; - } - catch (Exception e) - { - Logger.LogException(e); - if (OnConnectError != null) dispatchQueue.Enqueue(new OnConnectErrorMessage(OnConnectError, null, e.Message)); return; } @@ -195,7 +100,7 @@ public async Task Connect(string auth, string host, string nameOrAddress, Addres await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } - if (OnClose != null) dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, receiveResult.CloseStatus, null)); + if (OnClose != null) dispatchQueue.Enqueue(() => OnClose(receiveResult.CloseStatus, null)); return; } @@ -208,7 +113,7 @@ await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, var closeMessage = $"Maximum message size: {MAXMessageSize} bytes."; await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None); - if (OnClose != null) dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, WebSocketCloseStatus.MessageTooBig, null)); + if (OnClose != null) dispatchQueue.Enqueue(() => OnClose(WebSocketCloseStatus.MessageTooBig, null)); return; } @@ -218,11 +123,15 @@ await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, count += receiveResult.Count; } - if (OnMessage != null) dispatchQueue.Enqueue(new OnMessage(OnMessage, _receiveBuffer.Take(count).ToArray())); + if (OnMessage != null) + { + var message = _receiveBuffer.Take(count).ToArray(); + dispatchQueue.Enqueue(() => OnMessage(message)); + } } catch (WebSocketException ex) { - if (OnClose != null) dispatchQueue.Enqueue(new OnDisconnectMessage(OnClose, null, ex.WebSocketErrorCode)); + if (OnClose != null) dispatchQueue.Enqueue(() => OnClose(null, ex.WebSocketErrorCode)); return; } } @@ -278,7 +187,7 @@ private async Task ProcessSendQueue() catch (Exception e) { senderTask = null; - if (OnSendError != null) dispatchQueue.Enqueue(new OnSendErrorMessage(OnSendError, e)); + if (OnSendError != null) dispatchQueue.Enqueue(() => OnSendError(e)); } } @@ -291,7 +200,7 @@ public void Update() { while (dispatchQueue.TryDequeue(out var result)) { - result.Execute(); + result(); } } } From 8db08a7354c2a1e078801b4ef4b7a754268fd6b6 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 13 May 2024 12:07:28 -0400 Subject: [PATCH 076/223] Switch to TaskCompletionSource (#89) ## Description of Changes There is only one place where we use Channels, and it's to create and await a channel with one element - which is functionally the same as a more precise and low-weight TaskCompletionSource. Switching also makes the SDK compatible with the widely supported .NET Standard 2.1 subset, which is supported natively in Unity and allows to remove a custom System.Threading.Channels package from Unity SDK dependencies. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 2 +- sdks/csharp/src/SpacetimeDBClient.cs | 28 ++++++++++-------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index ea112980521..f8790c37609 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -1,7 +1,7 @@ - net7.0 + netstandard2.1 9 disable enable diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index bddc4e6c2f5..1a7bb1923b5 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -8,12 +8,10 @@ using System.Reflection; using System.Text; using System.Threading; -using System.Threading.Channels; using System.Threading.Tasks; using ClientApi; using Newtonsoft.Json; using SpacetimeDB.SATS; -using Channel = System.Threading.Channels.Channel; using Thread = System.Threading.Thread; namespace SpacetimeDB @@ -101,14 +99,11 @@ public struct DbOp private bool connectionClosed; public static ClientCache clientDB; - public static Dictionary> reducerEventCache = - new Dictionary>(); + private static Dictionary> reducerEventCache = new(); - public static Dictionary> deserializeEventCache = - new Dictionary>(); + private static Dictionary> deserializeEventCache = new(); - private static Dictionary> waitingOneOffQueries = - new Dictionary>(); + private static Dictionary> waitingOneOffQueries = new(); private bool isClosing; private Thread networkMessageProcessThread; @@ -459,16 +454,15 @@ HashSet GetInsertHashSet(string tableName, int tableSize) case ClientApi.Message.TypeOneofCase.OneOffQueryResponse: /// This case does NOT produce a list of DBOps, because it should not modify the client cache state! var resp = message.OneOffQueryResponse; - Guid messageId = new Guid(resp.MessageId.Span); + var messageId = new Guid(resp.MessageId.Span); - if (!waitingOneOffQueries.ContainsKey(messageId)) + if (!waitingOneOffQueries.Remove(messageId, out var resultSource)) { Logger.LogError("Response to unknown one-off-query: " + messageId); break; } - waitingOneOffQueries[messageId].Writer.TryWrite(resp); - waitingOneOffQueries.Remove(messageId); + resultSource.SetResult(resp); break; } @@ -897,10 +891,10 @@ public void Subscribe(List queries) /// Usage: SpacetimeDBClient.instance.OneOffQuery("WHERE sender = \"bob\""); public async Task OneOffQuery(string query) where T : IDatabaseTable { - Guid messageId = Guid.NewGuid(); - Type type = typeof(T); - Channel resultChannel = Channel.CreateBounded(1); - waitingOneOffQueries[messageId] = resultChannel; + var messageId = Guid.NewGuid(); + var type = typeof(T); + var resultSource = new TaskCompletionSource(); + waitingOneOffQueries[messageId] = resultSource; // unsanitized here, but writes will be prevented serverside. // the best they can do is send multiple selects, which will just result in them getting no data back. @@ -913,7 +907,7 @@ public async Task OneOffQuery(string query) where T : IDatabaseTable webSocket.Send(Encoding.UTF8.GetBytes(serializedQuery)); // Suspend for an arbitrary amount of time - var result = await resultChannel.Reader.ReadAsync(); + var result = await resultSource.Task; T[] LogAndThrow(string error) { From 6ba3da54667b6f825a01063e0d3cec6cfbb095a0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 14 May 2024 12:45:22 +0100 Subject: [PATCH 077/223] Minor refactoring of AuthToken (#84) ## Description of Changes Initially just fixed the nullability issues / warnings, but in the process did a few more minor drive-by refactorings. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/AuthToken.cs | 53 ++++++++++++++---------------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/sdks/csharp/src/AuthToken.cs b/sdks/csharp/src/AuthToken.cs index 134607c17a5..650120cf820 100644 --- a/sdks/csharp/src/AuthToken.cs +++ b/sdks/csharp/src/AuthToken.cs @@ -15,17 +15,17 @@ */ #if !UNITY_5_3_OR_NEWER using System; -using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; namespace SpacetimeDB { public static class AuthToken { - private static string? settingsPath = null; - private static string? token = null; + private static string? settingsPath; + private static string? token; + + private const string PREFIX = "auth_token="; /// /// Initializes the AuthToken class. This must be called before any other methods. @@ -36,10 +36,7 @@ public static class AuthToken /// public static void Init(string configFolder = ".spacetime_csharp_sdk", string configFile = "settings.ini", string? configRoot = null) { - if (configRoot == null) - { - configRoot = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - } + configRoot ??= Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); if (Environment.GetCommandLineArgs().Any(arg => arg == "--client")) { @@ -52,14 +49,10 @@ public static void Init(string configFolder = ".spacetime_csharp_sdk", string co if (File.Exists(settingsPath)) { - foreach (string line in File.ReadAllLines(settingsPath)) - { - if (line.StartsWith("auth_token=")) - { - token = line.Substring("auth_token=".Length); - break; - } - } + token = + File.ReadLines(settingsPath) + .FirstOrDefault(line => line.StartsWith(PREFIX)) + ?[PREFIX.Length..]; } } @@ -85,29 +78,23 @@ public static string? Token /// public static void SaveToken(string token) { + if (settingsPath == null) + { + throw new Exception("Token not initialized. Call AuthToken.Init() first."); + } Directory.CreateDirectory(Path.GetDirectoryName(settingsPath)!); - if (File.Exists(settingsPath)) + var newAuthLine = PREFIX + token; + var lines = File.Exists(settingsPath) ? File.ReadAllLines(settingsPath).ToList() : new(); + var i = lines.FindIndex(line => line.StartsWith(PREFIX)); + if (i >= 0) { - List lines = File.ReadAllLines(settingsPath).ToList(); - bool found = false; - for (int i = 0; i < lines.Count; i++) - { - if (lines[i].StartsWith("auth_token=")) - { - lines[i] = "auth_token=" + token; - found = true; - } - } - if (!found) - { - lines.Add("auth_token=" + token); - } - File.WriteAllLines(settingsPath, lines); + lines[i] = newAuthLine; } else { - File.WriteAllText(settingsPath, "auth_token=" + token); + lines.Add(newAuthLine); } + File.WriteAllLines(settingsPath, lines); } } } From 125c5e7bc205e96518f15efbbac0065b31cb53d0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 14 May 2024 12:48:52 +0100 Subject: [PATCH 078/223] NFC: inline insert/delete update handling (#86) ## Description of Changes Instead of a separate TableOp enum, and 4 fields to handle insert/delete metadata in DbOp, use a nullable struct that contains non-nullable object + bytes pair internally: - if `insert` is present (non-nullable) and `delete` is nullable, that naturally indicates insert operation - if `insert` is nullable and `delete` is not, that's a delete - if both are non-nullable, it's an update - if both are null, it's an internal "no change" state This simplifies and shortens update handling as well as reduces risk of state getting out of sync - e.g. TableOp saying that the operation is insert should exist but field containing inserted value being null. Now nullable struct itself communicates whether there is an insert or not, without a separate enum. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/SpacetimeDBClient.cs | 305 ++++++++------------------- 1 file changed, 86 insertions(+), 219 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 1a7bb1923b5..c7dade65722 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -18,14 +18,6 @@ namespace SpacetimeDB { public class SpacetimeDBClient { - public enum TableOp - { - Insert, - Delete, - Update, - NoChange, - } - public class ReducerCallRequest { public string fn; @@ -37,14 +29,23 @@ public class SubscriptionRequest public string subscriptionQuery; } - public struct DbOp + struct DbValue + { + public object value; + public byte[] bytes; + + public DbValue(object value, byte[] bytes) + { + this.value = value; + this.bytes = bytes; + } + } + + struct DbOp { public ClientCache.TableCache table; - public TableOp op; - public object newValue; - public object oldValue; - public byte[] deletedBytes; - public byte[] insertedBytes; + public DbValue? delete; + public DbValue? insert; public AlgebraicValue rowValue; } @@ -321,11 +322,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) var op = new DbOp { table = table, - deletedBytes = null, - insertedBytes = rowBytes, - op = TableOp.Insert, - newValue = obj, - oldValue = null, + insert = new(obj, rowBytes), rowValue = deserializedRow, }; @@ -375,24 +372,26 @@ HashSet GetInsertHashSet(string tableName, int tableSize) var op = new DbOp { table = table, - deletedBytes = - row.Op == TableRowOperation.Types.OperationType.Delete ? rowBytes : null, - insertedBytes = - row.Op == TableRowOperation.Types.OperationType.Delete ? null : rowBytes, - op = row.Op == TableRowOperation.Types.OperationType.Delete - ? TableOp.Delete - : TableOp.Insert, - newValue = row.Op == TableRowOperation.Types.OperationType.Delete ? null : obj, - oldValue = row.Op == TableRowOperation.Types.OperationType.Delete ? obj : null, rowValue = deserializedRow, }; + var dbValue = new DbValue(obj, rowBytes); + + if (row.Op == TableRowOperation.Types.OperationType.Insert) + { + op.insert = dbValue; + } + else + { + op.delete = dbValue; + } + if (primaryKeyType != null) { var primaryKeyLookup = GetPrimaryKeyLookup(tableName, primaryKeyType); - if (primaryKeyLookup.TryGetValue(primaryKeyValue, out var value)) + if (primaryKeyLookup.TryGetValue(primaryKeyValue, out var oldOp)) { - if (value.op == op.op || value.op == TableOp.Update) + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { Logger.LogWarning($"Update with the same primary key was " + $"applied multiple times! tableName={tableName}"); @@ -400,30 +399,17 @@ HashSet GetInsertHashSet(string tableName, int tableSize) // SpacetimeDB side. continue; } + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - var insertOp = op; - var deleteOp = value; - if (op.op == TableOp.Delete) - { - insertOp = value; - deleteOp = op; - } - - primaryKeyLookup[primaryKeyValue] = new DbOp + op = new DbOp { table = insertOp.table, - op = TableOp.Update, - newValue = insertOp.newValue, - oldValue = deleteOp.oldValue, - deletedBytes = deleteOp.deletedBytes, - insertedBytes = insertOp.insertedBytes, + delete = deleteOp.delete, + insert = insertOp.insert, rowValue = insertOp.rowValue, }; } - else - { - primaryKeyLookup[primaryKeyValue] = op; - } + primaryKeyLookup[primaryKeyValue] = op; } else { @@ -511,27 +497,20 @@ void ExecuteStateDiff() { foreach (var table in clientDB.GetTables()) { - foreach (var rowBytes in table.entries.Keys) + if (!preProcessedMessage.inserts.TryGetValue(table.Name, out var hashSet)) { - if (!preProcessedMessage.inserts.TryGetValue(table.Name, out var hashSet)) - { - continue; - } + continue; + } - if (!hashSet.Contains(rowBytes)) + foreach (var (rowBytes, oldValue) in table.entries.Where(kv => !hashSet.Contains(kv.Key))) + { + dbOps.Add(new DbOp { + table = table, // This is a row that we had before, but we do not have it now. // This must have been a delete. - dbOps.Add(new DbOp - { - table = table, - op = TableOp.Delete, - newValue = null, - oldValue = table.entries[rowBytes].Item2, - deletedBytes = rowBytes, - insertedBytes = null - }); - } + delete = new(oldValue.Item2, rowBytes), + }); } } } @@ -589,15 +568,16 @@ public void Connect(string token, string uri, string addressOrName) private void OnMessageProcessCompleteUpdate(Message message, List dbOps) { + var transactionEvent = message.TransactionUpdate?.Event!; + // First trigger OnBeforeDelete foreach (var update in dbOps) { - if (update.op == TableOp.Delete) + if (update.delete is { value: var oldValue }) { try { - update.table.BeforeDeleteCallback?.Invoke(update.oldValue, - message.TransactionUpdate?.Event); + update.table.BeforeDeleteCallback?.Invoke(oldValue, transactionEvent); } catch (Exception e) { @@ -606,175 +586,62 @@ private void OnMessageProcessCompleteUpdate(Message message, List dbOps) } } - void InternalDeleteCallback(DbOp op) - { - if (op.oldValue != null) - { - op.table.InternalValueDeletedCallback(op.oldValue); - } - else - { - Logger.LogError("Delete issued, but no value was present!"); - } - } - - void InternalInsertCallback(DbOp op) - { - if (op.newValue != null) - { - op.table.InternalValueInsertedCallback(op.newValue); - } - else - { - Logger.LogError("Insert issued, but no value was present!"); - } - } - // Apply all of the state for (var i = 0; i < dbOps.Count; i++) { // TODO: Reimplement updates when we add support for primary keys var update = dbOps[i]; - switch (update.op) + + if (update.delete is {} delete) { - case TableOp.Delete: - if (dbOps[i].table.DeleteEntry(update.deletedBytes)) - { - InternalDeleteCallback(update); - } - else - { - var op = dbOps[i]; - op.op = TableOp.NoChange; - dbOps[i] = op; - } - break; - case TableOp.Insert: - if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) - { - InternalInsertCallback(update); - } - else - { - var op = dbOps[i]; - op.op = TableOp.NoChange; - dbOps[i] = op; - } - break; - case TableOp.Update: - if (dbOps[i].table.DeleteEntry(update.deletedBytes)) - { - InternalDeleteCallback(update); - } - else - { - var op = dbOps[i]; - op.op = TableOp.NoChange; - dbOps[i] = op; - } + if (update.table.DeleteEntry(delete.bytes)) + { + update.table.InternalValueDeletedCallback(delete.value); + } + else + { + update.delete = null; + dbOps[i] = update; + } + } - if (dbOps[i].table.InsertEntry(update.insertedBytes, update.rowValue)) - { - InternalInsertCallback(update); - } - else - { - var op = dbOps[i]; - op.op = TableOp.NoChange; - dbOps[i] = op; - } - break; - default: - throw new ArgumentOutOfRangeException(); + if (update.insert is {} insert) + { + if (update.table.InsertEntry(insert.bytes, update.rowValue)) + { + update.table.InternalValueInsertedCallback(insert.value); + } + else + { + update.insert = null; + dbOps[i] = update; + } } } // Send out events - var updateCount = dbOps.Count; - for (var i = 0; i < updateCount; i++) + foreach (var dbOp in dbOps) { - var tableName = dbOps[i].table.ClientTableType.Name; - var tableOp = dbOps[i].op; - var oldValue = dbOps[i].oldValue; - var newValue = dbOps[i].newValue; - - switch (tableOp) + try { - case TableOp.Insert: - if (oldValue == null && newValue != null) - { - try - { - if (dbOps[i].table.InsertCallback != null) - { - dbOps[i].table.InsertCallback.Invoke(newValue, - message.TransactionUpdate?.Event); - } - } - catch (Exception e) - { - Logger.LogException(e); - } - } - else - { - Logger.LogError("Failed to send callback: invalid insert!"); - } - - break; - case TableOp.Delete: - { - if (oldValue != null && newValue == null) - { - if (dbOps[i].table.DeleteCallback != null) - { - try - { - dbOps[i].table.DeleteCallback.Invoke(oldValue, - message.TransactionUpdate?.Event); - } - catch (Exception e) - { - Logger.LogException(e); - } - } - } - else - { - Logger.LogError("Failed to send callback: invalid delete"); - } + switch (dbOp) + { + case { insert: { value: var newValue }, delete: { value: var oldValue } }: + dbOp.table.UpdateCallback?.Invoke(oldValue, newValue, transactionEvent); + break; + case { insert: { value: var newValue } }: + dbOp.table.InsertCallback?.Invoke(newValue, transactionEvent); break; - } - case TableOp.Update: - { - if (oldValue != null && newValue != null) - { - try - { - if (dbOps[i].table.UpdateCallback != null) - { - dbOps[i].table.UpdateCallback.Invoke(oldValue, newValue, - message.TransactionUpdate?.Event); - } - } - catch (Exception e) - { - Logger.LogException(e); - } - } - else - { - Logger.LogError("Failed to send callback: invalid update"); - } + case { delete: { value: var oldValue } }: + dbOp.table.DeleteCallback?.Invoke(oldValue, transactionEvent); break; - } - case TableOp.NoChange: - // noop - break; - default: - throw new ArgumentOutOfRangeException(); + } + } + catch (Exception e) + { + Logger.LogException(e); } } } From 1af72339f01aee9d48c6cf6fb5552f35c70934e3 Mon Sep 17 00:00:00 2001 From: Kurtis Mullins Date: Wed, 22 May 2024 12:49:34 -0400 Subject: [PATCH 079/223] Bump version for release v0.9 (#94) ## Description of Changes Bumped the version number to 0.9.0 as this was forgotten in the previous release. Includes all changes to date. ## API - [X] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* Not sure but its going out with the latest release. The previous package was 5 months ago. ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index f8790c37609..8d0a2523f35 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -18,7 +18,7 @@ README.md https://github.com/clockworklabs/spacetimedb-csharp-sdk 0.8.0 - 0.8.0 + 0.9.0 From ed6a3aac38106b843dd1f65624d8bc0061e7bbda Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 27 May 2024 18:49:44 +0100 Subject: [PATCH 080/223] Ignore duplicate inserts in the same subscription update (#92) ## Description of Changes Ignore duplicate inserts in the same subscription update ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/SpacetimeDBClient.cs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index c7dade65722..e3d00b037fb 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -302,6 +302,19 @@ HashSet GetInsertHashSet(string tableName, int tableSize) foreach (var row in update.TableRowOperations) { var rowBytes = row.Row.ToByteArray(); + + if (row.Op != TableRowOperation.Types.OperationType.Insert) + { + Logger.LogWarning("Non-insert during a subscription update!"); + continue; + } + + if (!hashSet.Add(rowBytes)) + { + // Ignore duplicate inserts in the same subscription update. + continue; + } + stream.Position = 0; stream.Write(rowBytes, 0, rowBytes.Length); stream.Position = 0; @@ -312,12 +325,6 @@ HashSet GetInsertHashSet(string tableName, int tableSize) throw new Exception("Failed to deserialize row"); } - if (row.Op != TableRowOperation.Types.OperationType.Insert) - { - Logger.LogWarning("Non-insert during a subscription update!"); - continue; - } - table.SetAndForgetDecodedValue(deserializedRow, out var obj); var op = new DbOp { @@ -326,14 +333,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) rowValue = deserializedRow, }; - if (!hashSet.Add(rowBytes)) - { - Logger.LogError($"Multiple of the same insert in the same subscription update: table={table.ClientTableType.Name} rowBytes={rowBytes}"); - } - else - { - dbOps.Add(op); - } + dbOps.Add(op); } } From 4819292d7485ea67b5e6b5b87d3815f8c46e7a33 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 28 May 2024 15:23:20 +0100 Subject: [PATCH 081/223] Simplify update handling as per consistent filtering proposal (#93) ## Description of Changes As a result of the consistent filtering rules proposal (clockworklabs/SpacetimeDB#1256), all equatable types are now natively equatable in C# as well. This allows us to compare objects directly, without holding and comparing AlgebraicValue in the entries map as well, which has a bit of a domino effect and allows to optimise, simplify or even remove some parts of the SDK. ## API - [x] This is an API breaking change to the SDK New filtering rules limit types on which filtering can be done, as well as change the return type of `FilterBy` functions to always be iterable. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/1277 --- .../examples/quickstart/client/Program.cs | 44 +- .../examples/quickstart/client/client.csproj | 2 +- .../client/module_bindings/Message.cs | 58 +-- .../client/module_bindings/ReducerEvent.cs | 24 +- .../module_bindings/ReducerJsonSettings.cs | 4 + .../module_bindings/SendMessageReducer.cs | 2 +- .../client/module_bindings/SetNameReducer.cs | 2 +- .../quickstart/client/module_bindings/User.cs | 64 +-- .../examples/quickstart/server/Cargo.lock | 450 +++++++++++++++--- .../examples/quickstart/server/Cargo.toml | 2 +- sdks/csharp/src/ClientCache.cs | 113 +---- sdks/csharp/src/SATS/AlgebraicValue.cs | 29 -- sdks/csharp/src/SpacetimeDBClient.cs | 61 +-- 13 files changed, 486 insertions(+), 369 deletions(-) diff --git a/sdks/csharp/examples/quickstart/client/Program.cs b/sdks/csharp/examples/quickstart/client/Program.cs index 9d4a2cc6279..96de1d1d970 100644 --- a/sdks/csharp/examples/quickstart/client/Program.cs +++ b/sdks/csharp/examples/quickstart/client/Program.cs @@ -1,13 +1,17 @@ -using SpacetimeDB; -using SpacetimeDB.Types; +using System; using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using SpacetimeDB; +using SpacetimeDB.Types; // our local client SpacetimeDB identity Identity? local_identity = null; -// declare a thread safe queue to store commands in format (command, args) -ConcurrentQueue<(string,string)> input_queue = new ConcurrentQueue<(string, string)>(); +// declare a thread safe queue to store commands +var input_queue = new ConcurrentQueue<(string Command, string Args)>(); // declare a threadsafe cancel token to cancel the process loop -CancellationTokenSource cancel_token = new CancellationTokenSource(); +var cancel_token = new CancellationTokenSource(); void Main() { @@ -41,11 +45,11 @@ void RegisterCallbacks() Reducer.OnSendMessageEvent += Reducer_OnSendMessageEvent; } -string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()!.Substring(0, 8); +string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()[..8]; void User_OnInsert(User insertedValue, ReducerEvent? dbEvent) { - if(insertedValue.Online) + if (insertedValue.Online) { Console.WriteLine($"{UserNameOrIdentity(insertedValue)} is online"); } @@ -53,13 +57,13 @@ void User_OnInsert(User insertedValue, ReducerEvent? dbEvent) void User_OnUpdate(User oldValue, User newValue, ReducerEvent? dbEvent) { - if(oldValue.Name != newValue.Name) + if (oldValue.Name != newValue.Name) { Console.WriteLine($"{UserNameOrIdentity(oldValue)} renamed to {newValue.Name}"); } - if(oldValue.Online != newValue.Online) + if (oldValue.Online != newValue.Online) { - if(newValue.Online) + if (newValue.Online) { Console.WriteLine($"{UserNameOrIdentity(newValue)} connected."); } @@ -72,9 +76,9 @@ void User_OnUpdate(User oldValue, User newValue, ReducerEvent? dbEvent) void PrintMessage(Message message) { - var sender = User.FilterByIdentity(message.Sender); + var sender = User.FindByIdentity(message.Sender); var senderName = "unknown"; - if(sender != null) + if (sender != null) { senderName = UserNameOrIdentity(sender); } @@ -84,7 +88,7 @@ void PrintMessage(Message message) void Message_OnInsert(Message insertedValue, ReducerEvent? dbEvent) { - if(dbEvent != null) + if (dbEvent != null) { PrintMessage(insertedValue); } @@ -92,7 +96,7 @@ void Message_OnInsert(Message insertedValue, ReducerEvent? dbEvent) void Reducer_OnSetNameEvent(ReducerEvent reducerEvent, string name) { - if(reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) + if (reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) { Console.Write($"Failed to change name to {name}"); } @@ -156,14 +160,14 @@ void InputLoop() while (true) { var input = Console.ReadLine(); - if(input == null) + if (input == null) { break; } - if(input.StartsWith("/name ")) + if (input.StartsWith("/name ")) { - input_queue.Enqueue(("name", input.Substring(6))); + input_queue.Enqueue(("name", input[6..])); continue; } else @@ -178,13 +182,13 @@ void ProcessCommands() // process input queue commands while (input_queue.TryDequeue(out var command)) { - switch (command.Item1) + switch (command.Command) { case "message": - Reducer.SendMessage(command.Item2); + Reducer.SendMessage(command.Args); break; case "name": - Reducer.SetName(command.Item2); + Reducer.SetName(command.Args); break; } } diff --git a/sdks/csharp/examples/quickstart/client/client.csproj b/sdks/csharp/examples/quickstart/client/client.csproj index 765c83b1394..f1a21bc707c 100644 --- a/sdks/csharp/examples/quickstart/client/client.csproj +++ b/sdks/csharp/examples/quickstart/client/client.csproj @@ -3,7 +3,7 @@ Exe net7.0 - enable + disable enable diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs index 438777e8545..2d475c122e6 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs @@ -2,8 +2,9 @@ // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. using System; -using System.Collections.Generic; using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; namespace SpacetimeDB.Types { @@ -43,9 +44,7 @@ public static SpacetimeDB.SATS.AlgebraicType GetAlgebraicType() public static explicit operator Message(SpacetimeDB.SATS.AlgebraicValue value) { - if (value == null) { - return null; - } + if (value == null) return null; var productValue = value.AsProductValue(); return new Message { @@ -55,58 +54,37 @@ public static explicit operator Message(SpacetimeDB.SATS.AlgebraicValue value) }; } - public static System.Collections.Generic.IEnumerable Iter() + public static IEnumerable Iter() { - foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("Message")) - { - yield return (Message)entry.Item2; - } + return SpacetimeDBClient.clientDB.GetObjects("Message").Cast(); } - public static int Count() + + public static IEnumerable Query(Func filter) { - return SpacetimeDBClient.clientDB.Count("Message"); + return Iter().Where(filter); } - public static System.Collections.Generic.IEnumerable FilterBySender(SpacetimeDB.Identity value) + + public static int Count() { - foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("Message")) - { - var productValue = entry.Item1.AsProductValue(); - var compareValue = Identity.From(productValue.elements[0].AsProductValue().elements[0].AsBytes()); - if (compareValue == value) { - yield return (Message)entry.Item2; - } - } + return SpacetimeDBClient.clientDB.Count("Message"); } - public static System.Collections.Generic.IEnumerable FilterBySent(ulong value) + public static IEnumerable FilterBySender(SpacetimeDB.Identity value) { - foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("Message")) - { - var productValue = entry.Item1.AsProductValue(); - var compareValue = (ulong)productValue.elements[1].AsU64(); - if (compareValue == value) { - yield return (Message)entry.Item2; - } - } + return Query(x => x.Sender == value); } - public static System.Collections.Generic.IEnumerable FilterByText(string value) + public static IEnumerable FilterBySent(ulong value) { - foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("Message")) - { - var productValue = entry.Item1.AsProductValue(); - var compareValue = (string)productValue.elements[2].AsString(); - if (compareValue == value) { - yield return (Message)entry.Item2; - } - } + return Query(x => x.Sent == value); } - public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, SpacetimeDB.SATS.AlgebraicValue _v1, SpacetimeDB.SATS.AlgebraicValue _v2) + public static IEnumerable FilterByText(string value) { - return false; + return Query(x => x.Text == value); } + public delegate void InsertEventHandler(Message insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void DeleteEventHandler(Message deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); public static event InsertEventHandler OnInsert; diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs index 57d56bef14d..ad63b2e07ca 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs @@ -2,9 +2,9 @@ // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. using System; +using SpacetimeDB; using ClientApi; using Newtonsoft.Json.Linq; -using SpacetimeDB; namespace SpacetimeDB.Types { @@ -41,27 +41,5 @@ public SetNameArgsStruct SetNameArgs return (SetNameArgsStruct)Args; } } - - public object[] GetArgsAsObjectArray() - { - switch (Reducer) - { - case ReducerType.SendMessage: - { - var args = SendMessageArgs; - return new object[] { - args.Text, - }; - } - case ReducerType.SetName: - { - var args = SetNameArgs; - return new object[] { - args.Name, - }; - } - default: throw new System.Exception($"Unhandled reducer case: {Reducer}. Please run SpacetimeDB code generator"); - } - } } } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs index f05fa36edee..7219233f10b 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs @@ -1,3 +1,7 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +using System; using SpacetimeDB; namespace SpacetimeDB.Types diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs index 931beb9a50b..be32649f03d 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs @@ -2,9 +2,9 @@ // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. using System; +using SpacetimeDB; using ClientApi; using Newtonsoft.Json.Linq; -using SpacetimeDB; namespace SpacetimeDB.Types { diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs index d97415b5fc8..e423752bc1e 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs @@ -2,9 +2,9 @@ // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. using System; +using SpacetimeDB; using ClientApi; using Newtonsoft.Json.Linq; -using SpacetimeDB; namespace SpacetimeDB.Types { diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs index 04230fc3e67..58f7a84fe25 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs @@ -2,8 +2,9 @@ // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. using System; -using System.Collections.Generic; using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; namespace SpacetimeDB.Types { @@ -18,7 +19,7 @@ public partial class User : IDatabaseTable [Newtonsoft.Json.JsonProperty("online")] public bool Online; - private static Dictionary Identity_Index = new Dictionary(16); + private static Dictionary Identity_Index = new(16); private static void InternalOnValueInserted(object insertedValue) { @@ -53,9 +54,7 @@ public static SpacetimeDB.SATS.AlgebraicType GetAlgebraicType() public static explicit operator User(SpacetimeDB.SATS.AlgebraicValue value) { - if (value == null) { - return null; - } + if (value == null) return null; var productValue = value.AsProductValue(); return new User { @@ -65,64 +64,39 @@ public static explicit operator User(SpacetimeDB.SATS.AlgebraicValue value) }; } - public static System.Collections.Generic.IEnumerable Iter() - { - foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("User")) - { - yield return (User)entry.Item2; - } - } - public static int Count() - { - return SpacetimeDBClient.clientDB.Count("User"); - } - public static User FilterByIdentity(SpacetimeDB.Identity value) + public static IEnumerable Iter() { - Identity_Index.TryGetValue(value, out var r); - return r; + return SpacetimeDBClient.clientDB.GetObjects("User").Cast(); } - public static System.Collections.Generic.IEnumerable FilterByName(string? value) + public static IEnumerable Query(Func filter) { - foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("User")) - { - var productValue = entry.Item1.AsProductValue(); - var compareValue = (string?)(productValue.elements[1].AsSumValue().tag == 1 ? null : productValue.elements[1].AsSumValue().value.AsString()); - if (compareValue == value) { - yield return (User)entry.Item2; - } - } + return Iter().Where(filter); } - public static System.Collections.Generic.IEnumerable FilterByOnline(bool value) + public static int Count() { - foreach(var entry in SpacetimeDBClient.clientDB.GetEntries("User")) - { - var productValue = entry.Item1.AsProductValue(); - var compareValue = (bool)productValue.elements[2].AsBool(); - if (compareValue == value) { - yield return (User)entry.Item2; - } - } + return SpacetimeDBClient.clientDB.Count("User"); } - public static bool ComparePrimaryKey(SpacetimeDB.SATS.AlgebraicType t, SpacetimeDB.SATS.AlgebraicValue v1, SpacetimeDB.SATS.AlgebraicValue v2) + public static User FindByIdentity(SpacetimeDB.Identity value) { - var primaryColumnValue1 = v1.AsProductValue().elements[0]; - var primaryColumnValue2 = v2.AsProductValue().elements[0]; - return SpacetimeDB.SATS.AlgebraicValue.Compare(t.product.elements[0].algebraicType, primaryColumnValue1, primaryColumnValue2); + Identity_Index.TryGetValue(value, out var r); + return r; } - public static SpacetimeDB.SATS.AlgebraicValue GetPrimaryKeyValue(SpacetimeDB.SATS.AlgebraicValue v) + public static IEnumerable FilterByIdentity(SpacetimeDB.Identity value) { - return v.AsProductValue().elements[0]; + return new[] { FindByIdentity(value) }; } - public static SpacetimeDB.SATS.AlgebraicType GetPrimaryKeyType(SpacetimeDB.SATS.AlgebraicType t) + public static IEnumerable FilterByOnline(bool value) { - return t.product.elements[0].algebraicType; + return Query(x => x.Online == value); } + private static object GetPrimaryKeyValue(object row) => ((User)row).Identity; + public delegate void InsertEventHandler(User insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void UpdateEventHandler(User oldValue, User newValue, SpacetimeDB.Types.ReducerEvent dbEvent); public delegate void DeleteEventHandler(User deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); diff --git a/sdks/csharp/examples/quickstart/server/Cargo.lock b/sdks/csharp/examples/quickstart/server/Cargo.lock index 2699863f7c3..77aa8859440 100644 --- a/sdks/csharp/examples/quickstart/server/Cargo.lock +++ b/sdks/csharp/examples/quickstart/server/Cargo.lock @@ -3,28 +3,28 @@ version = 3 [[package]] -name = "addr2line" -version = "0.21.0" +name = "ahash" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "gimli", + "cfg-if", + "once_cell", + "version_check", + "zerocopy", ] [[package]] -name = "adler" -version = "1.0.2" +name = "allocator-api2" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "anyhow" version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" -dependencies = [ - "backtrace", -] [[package]] name = "approx" @@ -48,19 +48,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "backtrace" -version = "0.3.69" +name = "bitflags" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block-buffer" @@ -71,21 +62,18 @@ dependencies = [ "generic-array", ] -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cpufeatures" version = "0.2.9" @@ -95,6 +83,31 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crypto-common" version = "0.1.6" @@ -115,6 +128,19 @@ dependencies = [ "num-traits", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + [[package]] name = "digest" version = "0.10.7" @@ -127,9 +153,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "enum-as-inner" @@ -140,9 +166,15 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.32", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "generic-array" version = "0.14.7" @@ -154,10 +186,16 @@ dependencies = [ ] [[package]] -name = "gimli" -version = "0.28.0" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", + "rayon", + "serde", +] [[package]] name = "heck" @@ -179,9 +217,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "itertools" -version = "0.10.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -195,12 +233,28 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.19" @@ -214,13 +268,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] -name = "miniz_oxide" -version = "0.7.1" +name = "nohash-hasher" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "num-traits" @@ -232,19 +283,39 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.32.1" +name = "once_cell" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ - "memchr", + "lock_api", + "parking_lot_core", ] [[package]] -name = "once_cell" -version = "1.18.0" +name = "parking_lot_core" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "proc-macro2" @@ -255,6 +326,27 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prometheus" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" +dependencies = [ + "cfg-if", + "fnv", + "lazy_static", + "memchr", + "parking_lot", + "protobuf", + "thiserror", +] + +[[package]] +name = "protobuf" +version = "2.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" + [[package]] name = "quote" version = "1.0.29" @@ -265,10 +357,42 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.23" +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] [[package]] name = "scoped-tls" @@ -276,6 +400,38 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "sha3" version = "0.10.8" @@ -286,6 +442,12 @@ dependencies = [ "keccak", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "spacetime-module" version = "0.1.0" @@ -297,71 +459,133 @@ dependencies = [ [[package]] name = "spacetimedb" -version = "0.6.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb2607c4aeda83c3568a5e371bc0a1caa0aa104732987814358bb7e062cf6ccf" +checksum = "e6521d61527095caf5afde8324c36f8a96555c1a5ab818aec27d933e7abc03cb" dependencies = [ + "derive_more", "log", - "once_cell", "scoped-tls", "spacetimedb-bindings-macro", "spacetimedb-bindings-sys", "spacetimedb-lib", + "spacetimedb-primitives", ] [[package]] name = "spacetimedb-bindings-macro" -version = "0.6.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6a9b4b143d79933f5e7f00d074ebc391d4f152ae2dd56be6beb1755532d7f6" +checksum = "14cb0093e45b8162365543edfb40d38d3494767fdeb2053f2d8574c7cf2f3d69" dependencies = [ + "bitflags", "humantime", "proc-macro2", "quote", - "syn", + "spacetimedb-primitives", + "syn 2.0.32", ] [[package]] name = "spacetimedb-bindings-sys" -version = "0.6.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6448feac3c8eea403c8cb1cf315958aec4e57c713c002ea8b9064fab9fea9fd9" +checksum = "f56d64f5a3121019e81668b1b473a280e0ca4c370c029806d786e4280fb66ce6" +dependencies = [ + "spacetimedb-primitives", +] + +[[package]] +name = "spacetimedb-data-structures" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35dee07b3444c0458449ceaa1031764e091d87037c73ed163c80b0481c74715" +dependencies = [ + "hashbrown", + "nohash-hasher", + "thiserror", +] [[package]] name = "spacetimedb-lib" -version = "0.6.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8297e4e5843d346bd7844366e3cdf3b1dfd9259b466166d4e9c8588106b967b5" +checksum = "7623594632219c3099e489820a32d0cc683c97ee9a1fe928288ef399960691ff" dependencies = [ "anyhow", + "bitflags", + "derive_more", "enum-as-inner", "hex", "itertools", - "sha3", "spacetimedb-bindings-macro", + "spacetimedb-metrics", + "spacetimedb-primitives", "spacetimedb-sats", "thiserror", ] +[[package]] +name = "spacetimedb-metrics" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55f007099699a71d5338d44eb8790ba307fcc2771c34565624ba213b9471ab0" +dependencies = [ + "arrayvec", + "itertools", + "paste", + "prometheus", +] + +[[package]] +name = "spacetimedb-primitives" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8350fd9d7df7234e965c433aaf46b134c00bddf645e80d2e3c7c0e824592959a" +dependencies = [ + "bitflags", + "either", + "spacetimedb-data-structures", +] + [[package]] name = "spacetimedb-sats" -version = "0.6.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d414893befd6b19e874243334cb5709348aedc7eae01db7813b17f10583ab8" +checksum = "1e60a059eabb85405a74b9d73751ff58d10fb2229d4b28e97c5519e6b305d2fc" dependencies = [ "arrayvec", + "bitflags", "decorum", + "derive_more", "enum-as-inner", + "hex", "itertools", + "sha3", + "smallvec", "spacetimedb-bindings-macro", + "spacetimedb-data-structures", + "spacetimedb-metrics", + "spacetimedb-primitives", "thiserror", ] [[package]] name = "syn" -version = "2.0.25" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" dependencies = [ "proc-macro2", "quote", @@ -385,7 +609,7 @@ checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.32", ] [[package]] @@ -405,3 +629,87 @@ name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] diff --git a/sdks/csharp/examples/quickstart/server/Cargo.toml b/sdks/csharp/examples/quickstart/server/Cargo.toml index bf8735590be..5bf84e2c7c0 100644 --- a/sdks/csharp/examples/quickstart/server/Cargo.toml +++ b/sdks/csharp/examples/quickstart/server/Cargo.toml @@ -9,6 +9,6 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -spacetimedb = "0.7" +spacetimedb = "0.9" log = "0.4" anyhow = "1.0" diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 93f82577e64..fb66925f2b3 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -3,8 +3,7 @@ using System.Collections.Generic; using System.Reflection; using SpacetimeDB.SATS; -using System.Numerics; -using System.Runtime.CompilerServices; +using System.Linq; namespace SpacetimeDB { @@ -12,7 +11,6 @@ public class ClientCache { public class TableCache { - private readonly string name; private readonly Type clientTableType; private readonly AlgebraicType rowSchema; @@ -20,7 +18,7 @@ public class TableCache private Func decoderFunc; // Maps from primary key to type value - public readonly Dictionary entries; + public readonly Dictionary entries = new(ByteArrayComparer.Instance); public Type ClientTableType { @@ -33,14 +31,7 @@ public Type ClientTableType public Action BeforeDeleteCallback; public Action DeleteCallback; public Action UpdateCallback; - public Func ComparePrimaryKeyFunc; - public Func GetPrimaryKeyValueFunc; - public Func GetPrimaryKeyTypeFunc; - - public string Name - { - get => name; - } + public Func GetPrimaryKeyValueFunc; public AlgebraicType RowSchema { @@ -49,7 +40,6 @@ public AlgebraicType RowSchema public TableCache(Type clientTableType, AlgebraicType rowSchema, Func decoderFunc) { - name = clientTableType.Name; this.clientTableType = clientTableType; this.rowSchema = rowSchema; @@ -60,13 +50,8 @@ public TableCache(Type clientTableType, AlgebraicType rowSchema, Func)clientTableType.GetMethod("OnBeforeDeleteEvent")?.CreateDelegate(typeof(Action)); DeleteCallback = (Action)clientTableType.GetMethod("OnDeleteEvent")?.CreateDelegate(typeof(Action)); UpdateCallback = (Action)clientTableType.GetMethod("OnUpdateEvent")?.CreateDelegate(typeof(Action)); - ComparePrimaryKeyFunc = (Func)clientTableType.GetMethod("ComparePrimaryKey", BindingFlags.Static | BindingFlags.Public) - ?.CreateDelegate(typeof(Func)); - GetPrimaryKeyValueFunc = (Func)clientTableType.GetMethod("GetPrimaryKeyValue", BindingFlags.Static | BindingFlags.Public) - ?.CreateDelegate(typeof(Func)); - GetPrimaryKeyTypeFunc = (Func)clientTableType.GetMethod("GetPrimaryKeyType", BindingFlags.Static | BindingFlags.Public) - ?.CreateDelegate(typeof(Func)); - entries = new Dictionary(new ByteArrayComparer()); + GetPrimaryKeyValueFunc = (Func)clientTableType.GetMethod("GetPrimaryKeyValue", BindingFlags.NonPublic | BindingFlags.Static) + ?.CreateDelegate(typeof(Func)); } /// @@ -83,19 +68,9 @@ public void SetAndForgetDecodedValue(AlgebraicValue value, out object obj) /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. /// /// The BSATN encoded bytes of the row to retrieve. - /// The parsed AlgebraicValue of the row encoded by the rowBytes. + /// The parsed row encoded by the rowBytes. /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. - public bool InsertEntry(byte[] rowBytes, AlgebraicValue value) - { - if (entries.ContainsKey(rowBytes)) - { - return false; - } - - // Insert the row into our table - entries[rowBytes] = (value, decoderFunc(value)); - return true; - } + public bool InsertEntry(byte[] rowBytes, object value) => entries.TryAdd(rowBytes, value); /// /// Deletes a value from the table. @@ -104,9 +79,8 @@ public bool InsertEntry(byte[] rowBytes, AlgebraicValue value) /// True if and only if the value was previously resident and has been deleted. public bool DeleteEntry(byte[] rowBytes) { - if (entries.TryGetValue(rowBytes, out var value)) + if (entries.Remove(rowBytes)) { - entries.Remove(rowBytes); return true; } @@ -114,37 +88,9 @@ public bool DeleteEntry(byte[] rowBytes) return false; } - /// - /// Gets a value from the table - /// - /// The BSATN encoded bytes of the row to retrieve. - /// Output: the parsed domain type corresponding to the rowBytes, or null if the row was not present in the cache. - /// True if and only if the value is resident and was stored in value. - public bool TryGetValue(byte[] rowBytes, out object value) - { - if (entries.TryGetValue(rowBytes, out var v)) - { - value = v.Item2; - return true; - } - - value = null; - return false; - } - - public bool ComparePrimaryKey(AlgebraicValue v1, AlgebraicValue v2) - { - return (bool)ComparePrimaryKeyFunc.Invoke(rowSchema, v1, v2); - } - - public AlgebraicValue GetPrimaryKeyValue(AlgebraicValue row) - { - return GetPrimaryKeyValueFunc != null ? GetPrimaryKeyValueFunc.Invoke(row) : null; - } - - public AlgebraicType GetPrimaryKeyType() + public object? GetPrimaryKeyValue(object row) { - return GetPrimaryKeyTypeFunc != null ? GetPrimaryKeyTypeFunc.Invoke(rowSchema) : null; + return GetPrimaryKeyValueFunc?.Invoke(row); } } @@ -165,33 +111,7 @@ public void AddTable(Type clientTableType, AlgebraicType tableRowDef, Func GetObjects(string name) - { - if (!tables.TryGetValue(name, out var table)) - { - yield break; - } - - foreach (var entry in table.entries) - { - yield return entry.Value.Item2; - } - } - - public IEnumerable<(AlgebraicValue, object)> GetEntries(string name) - { - if (!tables.TryGetValue(name, out var table)) - { - yield break; - } - - foreach (var entry in table.entries) - { - yield return entry.Value; - } - } - - public TableCache GetTable(string name) + public TableCache? GetTable(string name) { if (tables.TryGetValue(name, out var table)) { @@ -202,17 +122,12 @@ public TableCache GetTable(string name) return null; } - public int Count(string name) + public IEnumerable GetObjects(string name) { - if (!tables.TryGetValue(name, out var table)) - { - return 0; - } - - return table.entries.Count; + return GetTable(name)?.entries.Values ?? Enumerable.Empty(); } - public IEnumerable GetTableNames() => tables.Keys; + public int Count(string name) => GetTable(name)?.entries.Count ?? 0; public IEnumerable GetTables() => tables.Values; } diff --git a/sdks/csharp/src/SATS/AlgebraicValue.cs b/sdks/csharp/src/SATS/AlgebraicValue.cs index 9d78de35712..594d15a6022 100644 --- a/sdks/csharp/src/SATS/AlgebraicValue.cs +++ b/sdks/csharp/src/SATS/AlgebraicValue.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Collections.Generic; using System.IO; @@ -476,33 +475,5 @@ public void Serialize(AlgebraicType type, BinaryWriter writer) throw new NotImplementedException(); } } - - public class AlgebraicValueComparer : IEqualityComparer - { - private AlgebraicType type; - public AlgebraicValueComparer(AlgebraicType type) - { - this.type = type; - } - - public bool Equals(AlgebraicValue l, AlgebraicValue r) - { - return AlgebraicValue.Compare(type, l, r); - } - - public int GetHashCode(AlgebraicValue value) - { - var stream = new MemoryStream(); - var writer = new BinaryWriter(stream); - value.Serialize(type, writer); - var s = stream.ToArray(); - if (s.Length >= 4) - { - return BitConverter.ToInt32(s, 0); - } - return s.Sum(b => b); - } - } - } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index e3d00b037fb..00984b63b51 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -46,7 +46,6 @@ struct DbOp public ClientCache.TableCache table; public DbValue? delete; public DbValue? insert; - public AlgebraicValue rowValue; } /// @@ -215,7 +214,7 @@ struct PreProcessedMessage { public Message message; public List dbOps; - public Dictionary> inserts; + public Dictionary> inserts; } private readonly BlockingCollection _messageQueue = @@ -254,27 +253,16 @@ PreProcessedMessage PreProcessMessage(byte[] bytes) using var reader = new BinaryReader(stream); // This is all of the inserts - Dictionary> subscriptionInserts = null; + Dictionary> subscriptionInserts = null; // All row updates that have a primary key, this contains inserts, deletes and updates - var primaryKeyChanges = new Dictionary>(); + var primaryKeyChanges = new Dictionary<(System.Type tableType, object primaryKeyValue), DbOp>(); - Dictionary GetPrimaryKeyLookup(string tableName, AlgebraicType schema) + HashSet GetInsertHashSet(System.Type tableType, int tableSize) { - if (!primaryKeyChanges.TryGetValue(tableName, out var value)) - { - value = new Dictionary(new AlgebraicValue.AlgebraicValueComparer(schema)); - primaryKeyChanges[tableName] = value; - } - - return value; - } - - HashSet GetInsertHashSet(string tableName, int tableSize) - { - if (!subscriptionInserts.TryGetValue(tableName, out var hashSet)) + if (!subscriptionInserts.TryGetValue(tableType, out var hashSet)) { hashSet = new HashSet(capacity: tableSize, comparer: new ByteArrayComparer()); - subscriptionInserts[tableName] = hashSet; + subscriptionInserts[tableType] = hashSet; } return hashSet; @@ -285,13 +273,11 @@ HashSet GetInsertHashSet(string tableName, int tableSize) { case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: subscriptionUpdate = message.SubscriptionUpdate; - subscriptionInserts = new Dictionary>( - capacity: subscriptionUpdate.TableUpdates.Sum(a => a.TableRowOperations.Count)); + subscriptionInserts = new(capacity: subscriptionUpdate.TableUpdates.Sum(a => a.TableRowOperations.Count)); // First apply all of the state foreach (var update in subscriptionUpdate.TableUpdates) { var tableName = update.TableName; - var hashSet = GetInsertHashSet(tableName, subscriptionUpdate.TableUpdates.Count); var table = clientDB.GetTable(tableName); if (table == null) { @@ -299,6 +285,8 @@ HashSet GetInsertHashSet(string tableName, int tableSize) continue; } + var hashSet = GetInsertHashSet(table.ClientTableType, subscriptionUpdate.TableUpdates.Count); + foreach (var row in update.TableRowOperations) { var rowBytes = row.Row.ToByteArray(); @@ -330,7 +318,6 @@ HashSet GetInsertHashSet(string tableName, int tableSize) { table = table, insert = new(obj, rowBytes), - rowValue = deserializedRow, }; dbOps.Add(op); @@ -365,15 +352,10 @@ HashSet GetInsertHashSet(string tableName, int tableSize) throw new Exception("Failed to deserialize row"); } - var primaryKeyValue = table.GetPrimaryKeyValue(deserializedRow); - var primaryKeyType = table.GetPrimaryKeyType(); table.SetAndForgetDecodedValue(deserializedRow, out var obj); + var primaryKeyValue = table.GetPrimaryKeyValue(obj); - var op = new DbOp - { - table = table, - rowValue = deserializedRow, - }; + var op = new DbOp { table = table }; var dbValue = new DbValue(obj, rowBytes); @@ -386,10 +368,13 @@ HashSet GetInsertHashSet(string tableName, int tableSize) op.delete = dbValue; } - if (primaryKeyType != null) + if (primaryKeyValue != null) { - var primaryKeyLookup = GetPrimaryKeyLookup(tableName, primaryKeyType); - if (primaryKeyLookup.TryGetValue(primaryKeyValue, out var oldOp)) + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, primaryKeyValue); + + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { @@ -406,10 +391,10 @@ HashSet GetInsertHashSet(string tableName, int tableSize) table = insertOp.table, delete = deleteOp.delete, insert = insertOp.insert, - rowValue = insertOp.rowValue, }; } - primaryKeyLookup[primaryKeyValue] = op; + + primaryKeyChanges[key] = op; } else { @@ -419,7 +404,7 @@ HashSet GetInsertHashSet(string tableName, int tableSize) } // Combine primary key updates and non-primary key updates - dbOps.AddRange(primaryKeyChanges.Values.SelectMany(a => a.Values)); + dbOps.AddRange(primaryKeyChanges.Values); // Convert the generic event arguments in to a domain specific event object, this gets fed back into // the message.TransactionUpdate.Event.FunctionCall.CallInfo field. @@ -497,7 +482,7 @@ void ExecuteStateDiff() { foreach (var table in clientDB.GetTables()) { - if (!preProcessedMessage.inserts.TryGetValue(table.Name, out var hashSet)) + if (!preProcessedMessage.inserts.TryGetValue(table.ClientTableType, out var hashSet)) { continue; } @@ -509,7 +494,7 @@ void ExecuteStateDiff() table = table, // This is a row that we had before, but we do not have it now. // This must have been a delete. - delete = new(oldValue.Item2, rowBytes), + delete = new(oldValue, rowBytes), }); } } @@ -607,7 +592,7 @@ private void OnMessageProcessCompleteUpdate(Message message, List dbOps) if (update.insert is {} insert) { - if (update.table.InsertEntry(insert.bytes, update.rowValue)) + if (update.table.InsertEntry(insert.bytes, insert.value)) { update.table.InternalValueInsertedCallback(insert.value); } From 92f5a17ba7444f1ed1014e0b66810cc19f7063bf Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 28 May 2024 12:48:11 -0700 Subject: [PATCH 082/223] Bump version to 0.9.2 (#95) ## Description of Changes Just bumps the version number. Since 0.9.1 has been released, we are now on 0.9.2+! ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 8d0a2523f35..4339bf7b5b3 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -18,7 +18,7 @@ README.md https://github.com/clockworklabs/spacetimedb-csharp-sdk 0.8.0 - 0.9.0 + 0.9.2 From 7bafc7f1c77558e31f0596eaa7626f8f564643ba Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 7 Jun 2024 20:22:59 +0100 Subject: [PATCH 083/223] Switch to shared BSATN support (#97) ## Description of Changes See https://github.com/clockworklabs/SpacetimeDB/pull/1312 for the main description and API breakages. In the process extracted and simplified various common bits from generated code into the SDK itself to make generated code more concise. - Closes #67. - Closes #68. - Closes #73. - Closes #76. ## API - [x] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/1312 --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 2 +- .../examples/quickstart/client/Program.cs | 6 + .../examples/quickstart/client/client.csproj | 3 +- .../examples/quickstart/client/client.sln | 12 + .../client/module_bindings/Message.cs | 90 +-- .../client/module_bindings/ReducerEvent.cs | 45 -- .../module_bindings/ReducerJsonSettings.cs | 18 - .../module_bindings/SendMessageReducer.cs | 62 +-- .../client/module_bindings/SetNameReducer.cs | 62 +-- .../quickstart/client/module_bindings/User.cs | 112 +--- .../_Globals/SpacetimeDBClient.cs | 67 +++ .../_Globals/UnityNetworkManager.cs | 21 + .../examples/quickstart/server/src/lib.rs | 4 +- sdks/csharp/src/Address.cs | 73 ++- sdks/csharp/src/AuthToken.cs | 27 + sdks/csharp/src/BSATNHelpers.cs | 69 +++ sdks/csharp/src/ByteArrayConverter.cs | 23 - sdks/csharp/src/ClientApi.cs | 264 ++++++++- sdks/csharp/src/ClientApiExtensions.cs | 4 +- sdks/csharp/src/ClientCache.cs | 107 +--- sdks/csharp/src/IDatabaseTable.cs | 81 ++- sdks/csharp/src/Identity.cs | 59 +- sdks/csharp/src/NetworkManager.cs | 45 -- sdks/csharp/src/ReducerExtensions.cs | 18 - sdks/csharp/src/ReducerMismatchException.cs | 16 - sdks/csharp/src/SATS/AlgebraicType.cs | 197 ------- sdks/csharp/src/SATS/AlgebraicValue.cs | 479 ---------------- sdks/csharp/src/SATS/Typespace.cs | 30 - sdks/csharp/src/SpacetimeDBClient.cs | 513 +++++++----------- sdks/csharp/src/Stats.cs | 78 +++ sdks/csharp/src/Stubs.cs | 53 +- sdks/csharp/src/Utils.cs | 7 + sdks/csharp/src/WebSocket.cs | 18 +- sdks/csharp/src/json/EnumAttribute.cs | 11 - sdks/csharp/src/json/EnumWrapper.cs | 15 - sdks/csharp/src/json/EnumWrapperConverter.cs | 32 -- sdks/csharp/src/json/JsonContractResolver.cs | 70 --- sdks/csharp/src/json/SomeAttribute.cs | 11 - sdks/csharp/src/json/SomeWrapper.cs | 15 - sdks/csharp/src/json/SomeWrapperConverter.cs | 29 - 40 files changed, 1007 insertions(+), 1841 deletions(-) delete mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs delete mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs create mode 100644 sdks/csharp/examples/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs create mode 100644 sdks/csharp/src/BSATNHelpers.cs delete mode 100644 sdks/csharp/src/ByteArrayConverter.cs delete mode 100644 sdks/csharp/src/NetworkManager.cs delete mode 100644 sdks/csharp/src/ReducerExtensions.cs delete mode 100644 sdks/csharp/src/ReducerMismatchException.cs delete mode 100644 sdks/csharp/src/SATS/AlgebraicType.cs delete mode 100644 sdks/csharp/src/SATS/AlgebraicValue.cs delete mode 100644 sdks/csharp/src/SATS/Typespace.cs create mode 100644 sdks/csharp/src/Stats.cs delete mode 100644 sdks/csharp/src/json/EnumAttribute.cs delete mode 100644 sdks/csharp/src/json/EnumWrapper.cs delete mode 100644 sdks/csharp/src/json/EnumWrapperConverter.cs delete mode 100644 sdks/csharp/src/json/JsonContractResolver.cs delete mode 100644 sdks/csharp/src/json/SomeAttribute.cs delete mode 100644 sdks/csharp/src/json/SomeWrapper.cs delete mode 100644 sdks/csharp/src/json/SomeWrapperConverter.cs diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 4339bf7b5b3..2e976e56139 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -29,7 +29,7 @@ - + diff --git a/sdks/csharp/examples/quickstart/client/Program.cs b/sdks/csharp/examples/quickstart/client/Program.cs index 96de1d1d970..89b9329eb2f 100644 --- a/sdks/csharp/examples/quickstart/client/Program.cs +++ b/sdks/csharp/examples/quickstart/client/Program.cs @@ -35,6 +35,7 @@ void RegisterCallbacks() SpacetimeDBClient.instance.onConnect += OnConnect; SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; SpacetimeDBClient.instance.onSubscriptionApplied += OnSubscriptionApplied; + SpacetimeDBClient.instance.onUnhandledReducerError += onUnhandledReducerError; User.OnInsert += User_OnInsert; User.OnUpdate += User_OnUpdate; @@ -135,6 +136,11 @@ void OnSubscriptionApplied() PrintMessagesInOrder(); } +void onUnhandledReducerError(ReducerEvent reducerEvent) +{ + Console.WriteLine($"Unhandled reducer error in {reducerEvent.ReducerName}: {reducerEvent.ErrMessage}"); +} + const string HOST = "http://localhost:3000"; const string DBNAME = "chatqs"; diff --git a/sdks/csharp/examples/quickstart/client/client.csproj b/sdks/csharp/examples/quickstart/client/client.csproj index f1a21bc707c..edbe73206c3 100644 --- a/sdks/csharp/examples/quickstart/client/client.csproj +++ b/sdks/csharp/examples/quickstart/client/client.csproj @@ -8,9 +8,8 @@ - - + diff --git a/sdks/csharp/examples/quickstart/client/client.sln b/sdks/csharp/examples/quickstart/client/client.sln index 524c0df2b82..f14225a238c 100644 --- a/sdks/csharp/examples/quickstart/client/client.sln +++ b/sdks/csharp/examples/quickstart/client/client.sln @@ -7,6 +7,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "client.csproj", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpacetimeDB.ClientSDK", "..\..\..\SpacetimeDB.ClientSDK.csproj", "{242A8146-A58D-43E9-A2BD-31FFC6851AA6}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Codegen", "..\..\..\..\SpacetimeDB\crates\bindings-csharp\BSATN.Codegen\BSATN.Codegen.csproj", "{C7C0ED26-79E4-478B-8B15-71E2B078541D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Runtime", "..\..\..\..\SpacetimeDB\crates\bindings-csharp\BSATN.Runtime\BSATN.Runtime.csproj", "{BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +25,14 @@ Global {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.Build.0 = Release|Any CPU + {C7C0ED26-79E4-478B-8B15-71E2B078541D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7C0ED26-79E4-478B-8B15-71E2B078541D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7C0ED26-79E4-478B-8B15-71E2B078541D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7C0ED26-79E4-478B-8B15-71E2B078541D}.Release|Any CPU.Build.0 = Release|Any CPU + {BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs index 2d475c122e6..4676194ec9e 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs @@ -1,73 +1,27 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable using System; using SpacetimeDB; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace SpacetimeDB.Types { - [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)] - public partial class Message : IDatabaseTable + [SpacetimeDB.Type] + [DataContract] + public partial class Message : SpacetimeDB.DatabaseTable { - [Newtonsoft.Json.JsonProperty("sender")] - public SpacetimeDB.Identity Sender; - [Newtonsoft.Json.JsonProperty("sent")] + [DataMember(Name = "sender")] + public SpacetimeDB.Identity Sender = new(); + [DataMember(Name = "sent")] public ulong Sent; - [Newtonsoft.Json.JsonProperty("text")] - public string Text; - - - private static void InternalOnValueInserted(object insertedValue) - { - var val = (Message)insertedValue; - } - - private static void InternalOnValueDeleted(object deletedValue) - { - var val = (Message)deletedValue; - } - - public static SpacetimeDB.SATS.AlgebraicType GetAlgebraicType() - { - return SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] - { - new SpacetimeDB.SATS.ProductTypeElement("sender", SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] - { - new SpacetimeDB.SATS.ProductTypeElement("__identity_bytes", SpacetimeDB.SATS.AlgebraicType.CreateArrayType(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.U8))), - })), - new SpacetimeDB.SATS.ProductTypeElement("sent", SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.U64)), - new SpacetimeDB.SATS.ProductTypeElement("text", SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String)), - }); - } - - public static explicit operator Message(SpacetimeDB.SATS.AlgebraicValue value) - { - if (value == null) return null; - var productValue = value.AsProductValue(); - return new Message - { - Sender = SpacetimeDB.Identity.From(productValue.elements[0].AsProductValue().elements[0].AsBytes()), - Sent = productValue.elements[1].AsU64(), - Text = productValue.elements[2].AsString(), - }; - } - - public static IEnumerable Iter() - { - return SpacetimeDBClient.clientDB.GetObjects("Message").Cast(); - } - - public static IEnumerable Query(Func filter) - { - return Iter().Where(filter); - } - - public static int Count() - { - return SpacetimeDBClient.clientDB.Count("Message"); - } + [DataMember(Name = "text")] + public string Text = ""; public static IEnumerable FilterBySender(SpacetimeDB.Identity value) { @@ -85,25 +39,5 @@ public static IEnumerable FilterByText(string value) } - public delegate void InsertEventHandler(Message insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); - public delegate void DeleteEventHandler(Message deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); - public static event InsertEventHandler OnInsert; - public static event DeleteEventHandler OnBeforeDelete; - public static event DeleteEventHandler OnDelete; - - public static void OnInsertEvent(object newValue, ClientApi.Event dbEvent) - { - OnInsert?.Invoke((Message)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } - - public static void OnBeforeDeleteEvent(object oldValue, ClientApi.Event dbEvent) - { - OnBeforeDelete?.Invoke((Message)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } - - public static void OnDeleteEvent(object oldValue, ClientApi.Event dbEvent) - { - OnDelete?.Invoke((Message)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } } } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs deleted file mode 100644 index ad63b2e07ca..00000000000 --- a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerEvent.cs +++ /dev/null @@ -1,45 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. - -using System; -using SpacetimeDB; -using ClientApi; -using Newtonsoft.Json.Linq; - -namespace SpacetimeDB.Types -{ - public enum ReducerType - { - None, - SendMessage, - SetName, - } - - public partial class ReducerEvent : ReducerEventBase - { - public ReducerType Reducer { get; private set; } - - public ReducerEvent(ReducerType reducer, string reducerName, ulong timestamp, SpacetimeDB.Identity identity, SpacetimeDB.Address? callerAddress, string errMessage, ClientApi.Event.Types.Status status, object args) - : base(reducerName, timestamp, identity, callerAddress, errMessage, status, args) - { - Reducer = reducer; - } - - public SendMessageArgsStruct SendMessageArgs - { - get - { - if (Reducer != ReducerType.SendMessage) throw new SpacetimeDB.ReducerMismatchException(Reducer.ToString(), "SendMessage"); - return (SendMessageArgsStruct)Args; - } - } - public SetNameArgsStruct SetNameArgs - { - get - { - if (Reducer != ReducerType.SetName) throw new SpacetimeDB.ReducerMismatchException(Reducer.ToString(), "SetName"); - return (SetNameArgsStruct)Args; - } - } - } -} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs b/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs deleted file mode 100644 index 7219233f10b..00000000000 --- a/sdks/csharp/examples/quickstart/client/module_bindings/ReducerJsonSettings.cs +++ /dev/null @@ -1,18 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.Types -{ - [ReducerClass] - public partial class Reducer - { - private static Newtonsoft.Json.JsonSerializerSettings _settings = new Newtonsoft.Json.JsonSerializerSettings - { - Converters = { new SpacetimeDB.SomeWrapperConverter(), new SpacetimeDB.EnumWrapperConverter() }, - ContractResolver = new SpacetimeDB.JsonContractResolver(), - }; - } -} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs index be32649f03d..ffb537b63c5 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs @@ -1,61 +1,43 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable using System; using SpacetimeDB; -using ClientApi; -using Newtonsoft.Json.Linq; namespace SpacetimeDB.Types { + [SpacetimeDB.Type] + public partial class SendMessageArgsStruct : IReducerArgs + { + ReducerType IReducerArgs.ReducerType => ReducerType.SendMessage; + string IReducerArgsBase.ReducerName => "send_message"; + bool IReducerArgs.InvokeHandler(ReducerEvent reducerEvent) => Reducer.OnSendMessage(reducerEvent, this); + + public string Text = ""; + } + public static partial class Reducer { public delegate void SendMessageHandler(ReducerEvent reducerEvent, string text); - public static event SendMessageHandler OnSendMessageEvent; + public static event SendMessageHandler? OnSendMessageEvent; public static void SendMessage(string text) { - var _argArray = new object[] {text}; - var _message = new SpacetimeDBClient.ReducerCallRequest { - fn = "send_message", - args = _argArray, - }; - SpacetimeDBClient.instance.InternalCallReducer(Newtonsoft.Json.JsonConvert.SerializeObject(_message, _settings)); + SpacetimeDBClient.instance.InternalCallReducer(new SendMessageArgsStruct { Text = text }); } - [ReducerCallback(FunctionName = "send_message")] - public static bool OnSendMessage(ClientApi.Event dbEvent) + public static bool OnSendMessage(ReducerEvent reducerEvent, SendMessageArgsStruct args) { - if(OnSendMessageEvent != null) - { - var args = ((ReducerEvent)dbEvent.FunctionCall.CallInfo).SendMessageArgs; - OnSendMessageEvent((ReducerEvent)dbEvent.FunctionCall.CallInfo - ,(string)args.Text - ); - return true; - } - return false; + if (OnSendMessageEvent == null) return false; + OnSendMessageEvent( + reducerEvent, + args.Text + ); + return true; } - - [DeserializeEvent(FunctionName = "send_message")] - public static void SendMessageDeserializeEventArgs(ClientApi.Event dbEvent) - { - var args = new SendMessageArgsStruct(); - var bsatnBytes = dbEvent.FunctionCall.ArgBytes; - using var ms = new System.IO.MemoryStream(); - ms.SetLength(bsatnBytes.Length); - bsatnBytes.CopyTo(ms.GetBuffer(), 0); - ms.Position = 0; - using var reader = new System.IO.BinaryReader(ms); - var args_0_value = SpacetimeDB.SATS.AlgebraicValue.Deserialize(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String), reader); - args.Text = args_0_value.AsString(); - dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.SendMessage, "send_message", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), Address.From(dbEvent.CallerAddress.ToByteArray()), dbEvent.Message, dbEvent.Status, args); - } - } - - public partial class SendMessageArgsStruct - { - public string Text; } } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs b/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs index e423752bc1e..bdc3efd2578 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs @@ -1,61 +1,43 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable using System; using SpacetimeDB; -using ClientApi; -using Newtonsoft.Json.Linq; namespace SpacetimeDB.Types { + [SpacetimeDB.Type] + public partial class SetNameArgsStruct : IReducerArgs + { + ReducerType IReducerArgs.ReducerType => ReducerType.SetName; + string IReducerArgsBase.ReducerName => "set_name"; + bool IReducerArgs.InvokeHandler(ReducerEvent reducerEvent) => Reducer.OnSetName(reducerEvent, this); + + public string Name = ""; + } + public static partial class Reducer { public delegate void SetNameHandler(ReducerEvent reducerEvent, string name); - public static event SetNameHandler OnSetNameEvent; + public static event SetNameHandler? OnSetNameEvent; public static void SetName(string name) { - var _argArray = new object[] {name}; - var _message = new SpacetimeDBClient.ReducerCallRequest { - fn = "set_name", - args = _argArray, - }; - SpacetimeDBClient.instance.InternalCallReducer(Newtonsoft.Json.JsonConvert.SerializeObject(_message, _settings)); + SpacetimeDBClient.instance.InternalCallReducer(new SetNameArgsStruct { Name = name }); } - [ReducerCallback(FunctionName = "set_name")] - public static bool OnSetName(ClientApi.Event dbEvent) + public static bool OnSetName(ReducerEvent reducerEvent, SetNameArgsStruct args) { - if(OnSetNameEvent != null) - { - var args = ((ReducerEvent)dbEvent.FunctionCall.CallInfo).SetNameArgs; - OnSetNameEvent((ReducerEvent)dbEvent.FunctionCall.CallInfo - ,(string)args.Name - ); - return true; - } - return false; + if (OnSetNameEvent == null) return false; + OnSetNameEvent( + reducerEvent, + args.Name + ); + return true; } - - [DeserializeEvent(FunctionName = "set_name")] - public static void SetNameDeserializeEventArgs(ClientApi.Event dbEvent) - { - var args = new SetNameArgsStruct(); - var bsatnBytes = dbEvent.FunctionCall.ArgBytes; - using var ms = new System.IO.MemoryStream(); - ms.SetLength(bsatnBytes.Length); - bsatnBytes.CopyTo(ms.GetBuffer(), 0); - ms.Position = 0; - using var reader = new System.IO.BinaryReader(ms); - var args_0_value = SpacetimeDB.SATS.AlgebraicValue.Deserialize(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String), reader); - args.Name = args_0_value.AsString(); - dbEvent.FunctionCall.CallInfo = new ReducerEvent(ReducerType.SetName, "set_name", dbEvent.Timestamp, Identity.From(dbEvent.CallerIdentity.ToByteArray()), Address.From(dbEvent.CallerAddress.ToByteArray()), dbEvent.Message, dbEvent.Status, args); - } - } - - public partial class SetNameArgsStruct - { - public string Name; } } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs index 58f7a84fe25..94442532629 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/User.cs @@ -1,85 +1,41 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable using System; using SpacetimeDB; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace SpacetimeDB.Types { - [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)] - public partial class User : IDatabaseTable + [SpacetimeDB.Type] + [DataContract] + public partial class User : SpacetimeDB.DatabaseTableWithPrimaryKey { - [Newtonsoft.Json.JsonProperty("identity")] - public SpacetimeDB.Identity Identity; - [Newtonsoft.Json.JsonProperty("name")] - [SpacetimeDB.Some] - public string Name; - [Newtonsoft.Json.JsonProperty("online")] + [DataMember(Name = "identity")] + public SpacetimeDB.Identity Identity = new(); + [DataMember(Name = "name")] + public string? Name; + [DataMember(Name = "online")] public bool Online; private static Dictionary Identity_Index = new(16); - private static void InternalOnValueInserted(object insertedValue) - { - var val = (User)insertedValue; - Identity_Index[val.Identity] = val; - } - - private static void InternalOnValueDeleted(object deletedValue) - { - var val = (User)deletedValue; - Identity_Index.Remove(val.Identity); - } - - public static SpacetimeDB.SATS.AlgebraicType GetAlgebraicType() - { - return SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] - { - new SpacetimeDB.SATS.ProductTypeElement("identity", SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] - { - new SpacetimeDB.SATS.ProductTypeElement("__identity_bytes", SpacetimeDB.SATS.AlgebraicType.CreateArrayType(SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.U8))), - })), - new SpacetimeDB.SATS.ProductTypeElement("name", SpacetimeDB.SATS.AlgebraicType.CreateSumType(new System.Collections.Generic.List - { - new SpacetimeDB.SATS.SumTypeVariant("some", SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.String)), - new SpacetimeDB.SATS.SumTypeVariant("none", SpacetimeDB.SATS.AlgebraicType.CreateProductType(new SpacetimeDB.SATS.ProductTypeElement[] - { - })), - })), - new SpacetimeDB.SATS.ProductTypeElement("online", SpacetimeDB.SATS.AlgebraicType.CreatePrimitiveType(SpacetimeDB.SATS.BuiltinType.Type.Bool)), - }); - } - - public static explicit operator User(SpacetimeDB.SATS.AlgebraicValue value) - { - if (value == null) return null; - var productValue = value.AsProductValue(); - return new User - { - Identity = SpacetimeDB.Identity.From(productValue.elements[0].AsProductValue().elements[0].AsBytes()), - Name = productValue.elements[1].AsSumValue().tag == 1 ? null : productValue.elements[1].AsSumValue().value.AsString(), - Online = productValue.elements[2].AsBool(), - }; - } - - public static IEnumerable Iter() + public override void InternalOnValueInserted() { - return SpacetimeDBClient.clientDB.GetObjects("User").Cast(); + Identity_Index[Identity] = this; } - public static IEnumerable Query(Func filter) + public override void InternalOnValueDeleted() { - return Iter().Where(filter); + Identity_Index.Remove(Identity); } - public static int Count() - { - return SpacetimeDBClient.clientDB.Count("User"); - } - - public static User FindByIdentity(SpacetimeDB.Identity value) + public static User? FindByIdentity(SpacetimeDB.Identity value) { Identity_Index.TryGetValue(value, out var r); return r; @@ -87,7 +43,10 @@ public static User FindByIdentity(SpacetimeDB.Identity value) public static IEnumerable FilterByIdentity(SpacetimeDB.Identity value) { - return new[] { FindByIdentity(value) }; + if (FindByIdentity(value) is {} found) + { + yield return found; + } } public static IEnumerable FilterByOnline(bool value) @@ -95,34 +54,7 @@ public static IEnumerable FilterByOnline(bool value) return Query(x => x.Online == value); } - private static object GetPrimaryKeyValue(object row) => ((User)row).Identity; - - public delegate void InsertEventHandler(User insertedValue, SpacetimeDB.Types.ReducerEvent dbEvent); - public delegate void UpdateEventHandler(User oldValue, User newValue, SpacetimeDB.Types.ReducerEvent dbEvent); - public delegate void DeleteEventHandler(User deletedValue, SpacetimeDB.Types.ReducerEvent dbEvent); - public static event InsertEventHandler OnInsert; - public static event UpdateEventHandler OnUpdate; - public static event DeleteEventHandler OnBeforeDelete; - public static event DeleteEventHandler OnDelete; - - public static void OnInsertEvent(object newValue, ClientApi.Event dbEvent) - { - OnInsert?.Invoke((User)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } + public override object GetPrimaryKeyValue() => Identity; - public static void OnUpdateEvent(object oldValue, object newValue, ClientApi.Event dbEvent) - { - OnUpdate?.Invoke((User)oldValue,(User)newValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } - - public static void OnBeforeDeleteEvent(object oldValue, ClientApi.Event dbEvent) - { - OnBeforeDelete?.Invoke((User)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } - - public static void OnDeleteEvent(object oldValue, ClientApi.Event dbEvent) - { - OnDelete?.Invoke((User)oldValue,(ReducerEvent)dbEvent?.FunctionCall.CallInfo); - } } } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs new file mode 100644 index 00000000000..5748f597d9c --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs @@ -0,0 +1,67 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + public enum ReducerType + { + None, + SendMessage, + SetName, + } + + public interface IReducerArgs : IReducerArgsBase + { + ReducerType ReducerType { get; } + bool InvokeHandler(ReducerEvent reducerEvent); + } + + public partial class ReducerEvent : ReducerEventBase + { + public IReducerArgs? Args { get; } + + public string ReducerName => Args?.ReducerName ?? ""; + + [Obsolete("ReducerType is deprecated, please match directly on type of .Args instead.")] + public ReducerType Reducer => Args?.ReducerType ?? ReducerType.None; + + public ReducerEvent(IReducerArgs? args) : base() => Args = args; + public ReducerEvent(ClientApi.Event dbEvent, IReducerArgs? args) : base(dbEvent) => Args = args; + + [Obsolete("Accessors that implicitly cast `Args` are deprecated, please match `Args` against the desired type explicitly instead.")] + public SendMessageArgsStruct SendMessageArgs => (SendMessageArgsStruct)Args!; + [Obsolete("Accessors that implicitly cast `Args` are deprecated, please match `Args` against the desired type explicitly instead.")] + public SetNameArgsStruct SetNameArgs => (SetNameArgsStruct)Args!; + + public override bool InvokeHandler() => Args?.InvokeHandler(this) ?? false; + } + + public class SpacetimeDBClient : SpacetimeDBClientBase + { + protected SpacetimeDBClient() + { + clientDB.AddTable(); + clientDB.AddTable(); + } + + public static readonly SpacetimeDBClient instance = new(); + + protected override ReducerEvent ReducerEventFromDbEvent(ClientApi.Event dbEvent) + { + var argBytes = dbEvent.FunctionCall.ArgBytes; + IReducerArgs? args = dbEvent.FunctionCall.Reducer switch { + "send_message" => BSATNHelpers.FromProtoBytes(argBytes), + "set_name" => BSATNHelpers.FromProtoBytes(argBytes), + "" => null, + var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; + return new ReducerEvent(dbEvent, args); + } + } +} diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs b/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs new file mode 100644 index 00000000000..21ab1ef45b1 --- /dev/null +++ b/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs @@ -0,0 +1,21 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + // This class is only used in Unity projects. + // Attach this to a gameobject in your scene to use SpacetimeDB. + #if UNITY_5_3_OR_NEWER + public class UnityNetworkManager : UnityEngine.MonoBehaviour + { + private void OnDestroy() => SpacetimeDBClient.instance.Close(); + private void Update() => SpacetimeDBClient.instance.Update(); + } + #endif +} diff --git a/sdks/csharp/examples/quickstart/server/src/lib.rs b/sdks/csharp/examples/quickstart/server/src/lib.rs index 3083a346cc3..d47c6592b4f 100644 --- a/sdks/csharp/examples/quickstart/server/src/lib.rs +++ b/sdks/csharp/examples/quickstart/server/src/lib.rs @@ -1,7 +1,7 @@ use spacetimedb::{spacetimedb, ReducerContext, Identity, Timestamp}; use anyhow::{Result, anyhow}; -#[spacetimedb(table)] +#[spacetimedb(table(public))] pub struct User { #[primarykey] identity: Identity, @@ -9,7 +9,7 @@ pub struct User { online: bool, } -#[spacetimedb(table)] +#[spacetimedb(table(public))] pub struct Message { sender: Identity, sent: Timestamp, diff --git a/sdks/csharp/src/Address.cs b/sdks/csharp/src/Address.cs index ab18d36b4e0..ca4c3199309 100644 --- a/sdks/csharp/src/Address.cs +++ b/sdks/csharp/src/Address.cs @@ -1,72 +1,61 @@ - using System; -using System.Collections; -using System.Collections.Generic; +using System.IO; using System.Linq; -using SpacetimeDB.SATS; +using SpacetimeDB.BSATN; namespace SpacetimeDB { - public struct Address : IEquatable
    + public readonly struct Address : IEquatable
    { - private byte[] bytes; - public const int SIZE = 16; - public byte[] Bytes => bytes; + public readonly byte[] Bytes; + + private Address(byte[] bytes) => Bytes = bytes; - public static AlgebraicType GetAlgebraicType() + public readonly struct BSATN : IReadWrite
    { - return new AlgebraicType - { - type = AlgebraicType.Type.Builtin, - builtin = new BuiltinType - { - type = BuiltinType.Type.Array, - arrayType = new AlgebraicType + public Address Read(BinaryReader reader) => + new(ByteArray.Instance.Read(reader)); + + public void Write(BinaryWriter writer, Address value) => + ByteArray.Instance.Write(writer, value.Bytes); + + public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => + new AlgebraicType.Product( + new AggregateElement[] { - type = AlgebraicType.Type.Builtin, - builtin = new BuiltinType - { - type = BuiltinType.Type.U8 - } + new("__address_bytes", ByteArray.Instance.GetAlgebraicType(registrar)) } - } - }; + ); } - public static explicit operator Address(AlgebraicValue v) => new Address - { - bytes = v.AsBytes(), - }; - public static Address? From(byte[] bytes) { - if (bytes.All(b => b == 0)) { - return null; - } - return new Address + if (bytes.All(b => b == 0)) { - bytes = bytes, - }; + return null; + } + return new(bytes); } - public bool Equals(Address other) => ByteArrayComparer.Instance.Equals(bytes, other.bytes); + public bool Equals(Address other) => ByteArrayComparer.Instance.Equals(Bytes, other.Bytes); - public override bool Equals(object o) => o is Address other && Equals(other); + public override bool Equals(object? o) => o is Address other && Equals(other); public static bool operator ==(Address a, Address b) => a.Equals(b); public static bool operator !=(Address a, Address b) => !a.Equals(b); - public static Address Random() { - Random rnd = new Random(); + public static Address Random() + { + var random = new Random(); var bytes = new byte[16]; - rnd.NextBytes(bytes); - return new Address{ bytes = bytes, }; + random.NextBytes(bytes); + return new(bytes); } - public override int GetHashCode() => ByteArrayComparer.Instance.GetHashCode(bytes); + public override int GetHashCode() => ByteArrayComparer.Instance.GetHashCode(Bytes); - public override string ToString() => ByteArrayComparer.ToHexString(bytes); + public override string ToString() => ByteArrayComparer.ToHexString(Bytes); } } diff --git a/sdks/csharp/src/AuthToken.cs b/sdks/csharp/src/AuthToken.cs index 650120cf820..0b9dcddd87f 100644 --- a/sdks/csharp/src/AuthToken.cs +++ b/sdks/csharp/src/AuthToken.cs @@ -98,4 +98,31 @@ public static void SaveToken(string token) } } } +#else +using UnityEngine; + +namespace SpacetimeDB +{ + // This is an optional helper class to store your auth token in PlayerPrefs + // Override GetTokenKey() if you want to use a player pref key specific to your game + public static class AuthToken + { + public static string Token => PlayerPrefs.GetString(GetTokenKey()); + + public static void SaveToken(string token) + { + PlayerPrefs.SetString(GetTokenKey(), token); + } + + public static string GetTokenKey() + { + var key = "spacetimedb.identity_token"; + #if UNITY_EDITOR + // Different editors need different keys + key += $" - {Application.dataPath}"; + #endif + return key; + } + } +} #endif diff --git a/sdks/csharp/src/BSATNHelpers.cs b/sdks/csharp/src/BSATNHelpers.cs new file mode 100644 index 00000000000..ebb7afdd3d6 --- /dev/null +++ b/sdks/csharp/src/BSATNHelpers.cs @@ -0,0 +1,69 @@ +using System; +using Google.Protobuf; +using SpacetimeDB.BSATN; +using System.IO; + +namespace SpacetimeDB +{ + public static class BSATNHelpers + { + public static T FromStream(Stream stream) + where T : IStructuralReadWrite, new() + { + using var reader = new BinaryReader(stream); + return IStructuralReadWrite.Read(reader); + } + + // There is CommunityToolkit.HighPerformance that provides this, + // but it's not compatible with Unity as it relies on .NET intrinsics, + // so we need to implement our own. + class ProtoStream : Stream + { + private readonly ReadOnlyMemory memory; + + public ProtoStream(ByteString input) + { + memory = input.Memory; + } + + public override long Position { get; set; } + public override long Length => memory.Length; + + public override bool CanRead => true; + public override int Read(byte[] buffer, int offset, int count) + { + memory.Slice((int)Position, count).CopyTo(buffer.AsMemory(offset)); + Position += count; + return count; + } + + // Easy to implement, but not needed for our use cases. + public override bool CanSeek => false; + public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); + + + // Our stream is read-only. + public override bool CanWrite => false; + public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); + public override void Flush() {} + public override void SetLength(long value) => throw new NotSupportedException(); + } + + public static T FromProtoBytes(ByteString bytes) + where T : IStructuralReadWrite, new() + { + using var stream = new ProtoStream(bytes); + return FromStream(stream); + } + + public static ByteString ToProtoBytes(this T value) + where T : IStructuralReadWrite, new() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + value.WriteFields(writer); + // This is safe because we know we own args so nobody else will modify it. + return UnsafeByteOperations.UnsafeWrap(stream.ToArray()); + } + } +} diff --git a/sdks/csharp/src/ByteArrayConverter.cs b/sdks/csharp/src/ByteArrayConverter.cs deleted file mode 100644 index c60692e5d09..00000000000 --- a/sdks/csharp/src/ByteArrayConverter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using Newtonsoft.Json; - -namespace SpacetimeDB -{ - public class ByteArrayConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return objectType == typeof(byte[]); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteValue(ByteArrayComparer.ToHexString((byte[])value)); - } - } -} diff --git a/sdks/csharp/src/ClientApi.cs b/sdks/csharp/src/ClientApi.cs index ee8f38bc94a..6b382b93e90 100644 --- a/sdks/csharp/src/ClientApi.cs +++ b/sdks/csharp/src/ClientApi.cs @@ -35,44 +35,48 @@ static ClientApiReflection() { "eRgHIAEoCzIXLmNsaWVudF9hcGkuT25lT2ZmUXVlcnlIABI+ChNvbmVPZmZR", "dWVyeVJlc3BvbnNlGAggASgLMh8uY2xpZW50X2FwaS5PbmVPZmZRdWVyeVJl", "c3BvbnNlSABCBgoEdHlwZSJBCg1JZGVudGl0eVRva2VuEhAKCGlkZW50aXR5", - "GAEgASgMEg0KBXRva2VuGAIgASgJEg8KB2FkZHJlc3MYAyABKAwiMQoMRnVu", - "Y3Rpb25DYWxsEg8KB3JlZHVjZXIYASABKAkSEAoIYXJnQnl0ZXMYAiABKAwi", - "IgoJU3Vic2NyaWJlEhUKDXF1ZXJ5X3N0cmluZ3MYASADKAkisAIKBUV2ZW50", - "EhEKCXRpbWVzdGFtcBgBIAEoBBIWCg5jYWxsZXJJZGVudGl0eRgCIAEoDBIu", - "CgxmdW5jdGlvbkNhbGwYAyABKAsyGC5jbGllbnRfYXBpLkZ1bmN0aW9uQ2Fs", - "bBIoCgZzdGF0dXMYBCABKA4yGC5jbGllbnRfYXBpLkV2ZW50LlN0YXR1cxIP", - "CgdtZXNzYWdlGAUgASgJEhoKEmVuZXJneV9xdWFudGFfdXNlZBgGIAEoAxIm", - "Ch5ob3N0X2V4ZWN1dGlvbl9kdXJhdGlvbl9taWNyb3MYByABKAQSFQoNY2Fs", - "bGVyQWRkcmVzcxgIIAEoDCI2CgZTdGF0dXMSDQoJY29tbWl0dGVkEAASCgoG", - "ZmFpbGVkEAESEQoNb3V0X29mX2VuZXJneRACIkMKElN1YnNjcmlwdGlvblVw", - "ZGF0ZRItCgx0YWJsZVVwZGF0ZXMYASADKAsyFy5jbGllbnRfYXBpLlRhYmxl", - "VXBkYXRlImwKC1RhYmxlVXBkYXRlEg8KB3RhYmxlSWQYASABKA0SEQoJdGFi", - "bGVOYW1lGAIgASgJEjkKEnRhYmxlUm93T3BlcmF0aW9ucxgDIAMoCzIdLmNs", - "aWVudF9hcGkuVGFibGVSb3dPcGVyYXRpb24iggEKEVRhYmxlUm93T3BlcmF0", - "aW9uEjcKAm9wGAEgASgOMisuY2xpZW50X2FwaS5UYWJsZVJvd09wZXJhdGlv", - "bi5PcGVyYXRpb25UeXBlEgsKA3JvdxgDIAEoDCInCg1PcGVyYXRpb25UeXBl", - "EgoKBkRFTEVURRAAEgoKBklOU0VSVBABInEKEVRyYW5zYWN0aW9uVXBkYXRl", - "EiAKBWV2ZW50GAEgASgLMhEuY2xpZW50X2FwaS5FdmVudBI6ChJzdWJzY3Jp", - "cHRpb25VcGRhdGUYAiABKAsyHi5jbGllbnRfYXBpLlN1YnNjcmlwdGlvblVw", - "ZGF0ZSI1CgtPbmVPZmZRdWVyeRIRCgltZXNzYWdlSWQYASABKAwSEwoLcXVl", - "cnlTdHJpbmcYAiABKAkiYAoTT25lT2ZmUXVlcnlSZXNwb25zZRIRCgltZXNz", - "YWdlSWQYASABKAwSDQoFZXJyb3IYAiABKAkSJwoGdGFibGVzGAMgAygLMhcu", - "Y2xpZW50X2FwaS5PbmVPZmZUYWJsZSItCgtPbmVPZmZUYWJsZRIRCgl0YWJs", - "ZU5hbWUYAiABKAkSCwoDcm93GAQgAygMYgZwcm90bzM=")); + "GAEgASgMEg0KBXRva2VuGAIgASgJEg8KB2FkZHJlc3MYAyABKAwiRAoMRnVu", + "Y3Rpb25DYWxsEg8KB3JlZHVjZXIYASABKAkSEAoIYXJnQnl0ZXMYAiABKAwS", + "EQoJcmVxdWVzdElkGAMgASgNIjUKCVN1YnNjcmliZRIVCg1xdWVyeV9zdHJp", + "bmdzGAEgAygJEhEKCXJlcXVlc3RJZBgCIAEoDSKwAgoFRXZlbnQSEQoJdGlt", + "ZXN0YW1wGAEgASgEEhYKDmNhbGxlcklkZW50aXR5GAIgASgMEi4KDGZ1bmN0", + "aW9uQ2FsbBgDIAEoCzIYLmNsaWVudF9hcGkuRnVuY3Rpb25DYWxsEigKBnN0", + "YXR1cxgEIAEoDjIYLmNsaWVudF9hcGkuRXZlbnQuU3RhdHVzEg8KB21lc3Nh", + "Z2UYBSABKAkSGgoSZW5lcmd5X3F1YW50YV91c2VkGAYgASgDEiYKHmhvc3Rf", + "ZXhlY3V0aW9uX2R1cmF0aW9uX21pY3JvcxgHIAEoBBIVCg1jYWxsZXJBZGRy", + "ZXNzGAggASgMIjYKBlN0YXR1cxINCgljb21taXR0ZWQQABIKCgZmYWlsZWQQ", + "ARIRCg1vdXRfb2ZfZW5lcmd5EAIihAEKElN1YnNjcmlwdGlvblVwZGF0ZRIt", + "Cgx0YWJsZVVwZGF0ZXMYASADKAsyFy5jbGllbnRfYXBpLlRhYmxlVXBkYXRl", + "EhEKCXJlcXVlc3RJZBgCIAEoDRIsCiR0b3RhbF9ob3N0X2V4ZWN1dGlvbl9k", + "dXJhdGlvbl9taWNyb3MYAyABKAQibAoLVGFibGVVcGRhdGUSDwoHdGFibGVJ", + "ZBgBIAEoDRIRCgl0YWJsZU5hbWUYAiABKAkSOQoSdGFibGVSb3dPcGVyYXRp", + "b25zGAMgAygLMh0uY2xpZW50X2FwaS5UYWJsZVJvd09wZXJhdGlvbiKCAQoR", + "VGFibGVSb3dPcGVyYXRpb24SNwoCb3AYASABKA4yKy5jbGllbnRfYXBpLlRh", + "YmxlUm93T3BlcmF0aW9uLk9wZXJhdGlvblR5cGUSCwoDcm93GAMgASgMIicK", + "DU9wZXJhdGlvblR5cGUSCgoGREVMRVRFEAASCgoGSU5TRVJUEAEicQoRVHJh", + "bnNhY3Rpb25VcGRhdGUSIAoFZXZlbnQYASABKAsyES5jbGllbnRfYXBpLkV2", + "ZW50EjoKEnN1YnNjcmlwdGlvblVwZGF0ZRgCIAEoCzIeLmNsaWVudF9hcGku", + "U3Vic2NyaXB0aW9uVXBkYXRlIjUKC09uZU9mZlF1ZXJ5EhEKCW1lc3NhZ2VJ", + "ZBgBIAEoDBITCgtxdWVyeVN0cmluZxgCIAEoCSKOAQoTT25lT2ZmUXVlcnlS", + "ZXNwb25zZRIRCgltZXNzYWdlSWQYASABKAwSDQoFZXJyb3IYAiABKAkSJwoG", + "dGFibGVzGAMgAygLMhcuY2xpZW50X2FwaS5PbmVPZmZUYWJsZRIsCiR0b3Rh", + "bF9ob3N0X2V4ZWN1dGlvbl9kdXJhdGlvbl9taWNyb3MYBCABKAQiLQoLT25l", + "T2ZmVGFibGUSEQoJdGFibGVOYW1lGAIgASgJEgsKA3JvdxgEIAMoDGIGcHJv", + "dG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Message), global::ClientApi.Message.Parser, new[]{ "FunctionCall", "SubscriptionUpdate", "Event", "TransactionUpdate", "IdentityToken", "Subscribe", "OneOffQuery", "OneOffQueryResponse" }, new[]{ "Type" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.IdentityToken), global::ClientApi.IdentityToken.Parser, new[]{ "Identity", "Token", "Address" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.FunctionCall), global::ClientApi.FunctionCall.Parser, new[]{ "Reducer", "ArgBytes" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Subscribe), global::ClientApi.Subscribe.Parser, new[]{ "QueryStrings" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.FunctionCall), global::ClientApi.FunctionCall.Parser, new[]{ "Reducer", "ArgBytes", "RequestId" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Subscribe), global::ClientApi.Subscribe.Parser, new[]{ "QueryStrings", "RequestId" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Event), global::ClientApi.Event.Parser, new[]{ "Timestamp", "CallerIdentity", "FunctionCall", "Status", "Message", "EnergyQuantaUsed", "HostExecutionDurationMicros", "CallerAddress" }, null, new[]{ typeof(global::ClientApi.Event.Types.Status) }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.SubscriptionUpdate), global::ClientApi.SubscriptionUpdate.Parser, new[]{ "TableUpdates" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.SubscriptionUpdate), global::ClientApi.SubscriptionUpdate.Parser, new[]{ "TableUpdates", "RequestId", "TotalHostExecutionDurationMicros" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableUpdate), global::ClientApi.TableUpdate.Parser, new[]{ "TableId", "TableName", "TableRowOperations" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableRowOperation), global::ClientApi.TableRowOperation.Parser, new[]{ "Op", "Row" }, null, new[]{ typeof(global::ClientApi.TableRowOperation.Types.OperationType) }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TransactionUpdate), global::ClientApi.TransactionUpdate.Parser, new[]{ "Event", "SubscriptionUpdate" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQuery), global::ClientApi.OneOffQuery.Parser, new[]{ "MessageId", "QueryString" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQueryResponse), global::ClientApi.OneOffQueryResponse.Parser, new[]{ "MessageId", "Error", "Tables" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQueryResponse), global::ClientApi.OneOffQueryResponse.Parser, new[]{ "MessageId", "Error", "Tables", "TotalHostExecutionDurationMicros" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffTable), global::ClientApi.OneOffTable.Parser, new[]{ "TableName", "Row" }, null, null, null, null) })); } @@ -86,6 +90,7 @@ static ClientApiReflection() { /// but I don't think we want to do that yet. /// TODO: Split this up into ServerBound and ClientBound if there's no overlap ///
    + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class Message : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -724,6 +729,7 @@ public void MergeFrom(pb::CodedInputStream input) { //// If the client connected anonymously, //// the database will generate new credentials to identify it. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class IdentityToken : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -994,10 +1000,12 @@ public void MergeFrom(pb::CodedInputStream input) { //// //// - `argBytes` is the arguments to the reducer, encoded as BSATN. //// + //// - `requestId` is a identifier for client request. //// SpacetimeDB models reducers as taking a single `AlgebraicValue` as an argument, which //// generally will be a `ProductValue` containing all of the args (except the //// `ReducerContext`, which is injected by the host, not provided in this API). /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class FunctionCall : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -1034,6 +1042,7 @@ public FunctionCall() { public FunctionCall(FunctionCall other) : this() { reducer_ = other.reducer_; argBytes_ = other.argBytes_; + requestId_ = other.requestId_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -1070,6 +1079,18 @@ public string Reducer { } } + /// Field number for the "requestId" field. + public const int RequestIdFieldNumber = 3; + private uint requestId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint RequestId { + get { return requestId_; } + set { + requestId_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -1087,6 +1108,7 @@ public bool Equals(FunctionCall other) { } if (Reducer != other.Reducer) return false; if (ArgBytes != other.ArgBytes) return false; + if (RequestId != other.RequestId) return false; return Equals(_unknownFields, other._unknownFields); } @@ -1096,6 +1118,7 @@ public override int GetHashCode() { int hash = 1; if (Reducer.Length != 0) hash ^= Reducer.GetHashCode(); if (ArgBytes.Length != 0) hash ^= ArgBytes.GetHashCode(); + if (RequestId != 0) hash ^= RequestId.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -1122,6 +1145,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(18); output.WriteBytes(ArgBytes); } + if (RequestId != 0) { + output.WriteRawTag(24); + output.WriteUInt32(RequestId); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -1140,6 +1167,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(18); output.WriteBytes(ArgBytes); } + if (RequestId != 0) { + output.WriteRawTag(24); + output.WriteUInt32(RequestId); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -1156,6 +1187,9 @@ public int CalculateSize() { if (ArgBytes.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(ArgBytes); } + if (RequestId != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(RequestId); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -1174,6 +1208,9 @@ public void MergeFrom(FunctionCall other) { if (other.ArgBytes.Length != 0) { ArgBytes = other.ArgBytes; } + if (other.RequestId != 0) { + RequestId = other.RequestId; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1197,6 +1234,10 @@ public void MergeFrom(pb::CodedInputStream input) { ArgBytes = input.ReadBytes(); break; } + case 24: { + RequestId = input.ReadUInt32(); + break; + } } } #endif @@ -1220,6 +1261,10 @@ public void MergeFrom(pb::CodedInputStream input) { ArgBytes = input.ReadBytes(); break; } + case 24: { + RequestId = input.ReadUInt32(); + break; + } } } } @@ -1245,6 +1290,7 @@ public void MergeFrom(pb::CodedInputStream input) { //// `SubscriptionUpdate` containing every existing row that matches `B`, even if some were //// already in `A`. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class Subscribe : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -1280,6 +1326,7 @@ public Subscribe() { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public Subscribe(Subscribe other) : this() { queryStrings_ = other.queryStrings_.Clone(); + requestId_ = other.requestId_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -1300,6 +1347,18 @@ public Subscribe Clone() { get { return queryStrings_; } } + /// Field number for the "requestId" field. + public const int RequestIdFieldNumber = 2; + private uint requestId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint RequestId { + get { return requestId_; } + set { + requestId_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -1316,6 +1375,7 @@ public bool Equals(Subscribe other) { return true; } if(!queryStrings_.Equals(other.queryStrings_)) return false; + if (RequestId != other.RequestId) return false; return Equals(_unknownFields, other._unknownFields); } @@ -1324,6 +1384,7 @@ public bool Equals(Subscribe other) { public override int GetHashCode() { int hash = 1; hash ^= queryStrings_.GetHashCode(); + if (RequestId != 0) hash ^= RequestId.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -1343,6 +1404,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawMessage(this); #else queryStrings_.WriteTo(output, _repeated_queryStrings_codec); + if (RequestId != 0) { + output.WriteRawTag(16); + output.WriteUInt32(RequestId); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -1354,6 +1419,10 @@ public void WriteTo(pb::CodedOutputStream output) { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { queryStrings_.WriteTo(ref output, _repeated_queryStrings_codec); + if (RequestId != 0) { + output.WriteRawTag(16); + output.WriteUInt32(RequestId); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -1365,6 +1434,9 @@ public void WriteTo(pb::CodedOutputStream output) { public int CalculateSize() { int size = 0; size += queryStrings_.CalculateSize(_repeated_queryStrings_codec); + if (RequestId != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(RequestId); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -1378,6 +1450,9 @@ public void MergeFrom(Subscribe other) { return; } queryStrings_.Add(other.queryStrings_); + if (other.RequestId != 0) { + RequestId = other.RequestId; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1397,6 +1472,10 @@ public void MergeFrom(pb::CodedInputStream input) { queryStrings_.AddEntriesFrom(input, _repeated_queryStrings_codec); break; } + case 16: { + RequestId = input.ReadUInt32(); + break; + } } } #endif @@ -1416,6 +1495,10 @@ public void MergeFrom(pb::CodedInputStream input) { queryStrings_.AddEntriesFrom(ref input, _repeated_queryStrings_codec); break; } + case 16: { + RequestId = input.ReadUInt32(); + break; + } } } } @@ -1465,6 +1548,7 @@ public void MergeFrom(pb::CodedInputStream input) { //// if and only if one was provided to the `call` HTTP endpoint. //// Reducers invoked by WebSocket will always have a `callerAddress`. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class Event : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -1947,7 +2031,14 @@ public enum Status { //// //// A single `SubscriptionUpdate` may contain `TableUpdate` messages for multiple //// tables. + //// - `requestId` is identifier sent by the client in requests, Host should ensure to + //// to include the same requestId in the response. + //// + //// - `total_host_execution_duration_micros` its the overall time between Host recevived a request + //// and sent a `TransactionUpdate` or `SubscriptionUpdate`. + //// '0' is default value. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class SubscriptionUpdate : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -1983,6 +2074,8 @@ public SubscriptionUpdate() { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public SubscriptionUpdate(SubscriptionUpdate other) : this() { tableUpdates_ = other.tableUpdates_.Clone(); + requestId_ = other.requestId_; + totalHostExecutionDurationMicros_ = other.totalHostExecutionDurationMicros_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -2003,6 +2096,30 @@ public SubscriptionUpdate Clone() { get { return tableUpdates_; } } + /// Field number for the "requestId" field. + public const int RequestIdFieldNumber = 2; + private uint requestId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint RequestId { + get { return requestId_; } + set { + requestId_ = value; + } + } + + /// Field number for the "total_host_execution_duration_micros" field. + public const int TotalHostExecutionDurationMicrosFieldNumber = 3; + private ulong totalHostExecutionDurationMicros_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong TotalHostExecutionDurationMicros { + get { return totalHostExecutionDurationMicros_; } + set { + totalHostExecutionDurationMicros_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -2019,6 +2136,8 @@ public bool Equals(SubscriptionUpdate other) { return true; } if(!tableUpdates_.Equals(other.tableUpdates_)) return false; + if (RequestId != other.RequestId) return false; + if (TotalHostExecutionDurationMicros != other.TotalHostExecutionDurationMicros) return false; return Equals(_unknownFields, other._unknownFields); } @@ -2027,6 +2146,8 @@ public bool Equals(SubscriptionUpdate other) { public override int GetHashCode() { int hash = 1; hash ^= tableUpdates_.GetHashCode(); + if (RequestId != 0) hash ^= RequestId.GetHashCode(); + if (TotalHostExecutionDurationMicros != 0UL) hash ^= TotalHostExecutionDurationMicros.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -2046,6 +2167,14 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawMessage(this); #else tableUpdates_.WriteTo(output, _repeated_tableUpdates_codec); + if (RequestId != 0) { + output.WriteRawTag(16); + output.WriteUInt32(RequestId); + } + if (TotalHostExecutionDurationMicros != 0UL) { + output.WriteRawTag(24); + output.WriteUInt64(TotalHostExecutionDurationMicros); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -2057,6 +2186,14 @@ public void WriteTo(pb::CodedOutputStream output) { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { tableUpdates_.WriteTo(ref output, _repeated_tableUpdates_codec); + if (RequestId != 0) { + output.WriteRawTag(16); + output.WriteUInt32(RequestId); + } + if (TotalHostExecutionDurationMicros != 0UL) { + output.WriteRawTag(24); + output.WriteUInt64(TotalHostExecutionDurationMicros); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -2068,6 +2205,12 @@ public void WriteTo(pb::CodedOutputStream output) { public int CalculateSize() { int size = 0; size += tableUpdates_.CalculateSize(_repeated_tableUpdates_codec); + if (RequestId != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(RequestId); + } + if (TotalHostExecutionDurationMicros != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(TotalHostExecutionDurationMicros); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -2081,6 +2224,12 @@ public void MergeFrom(SubscriptionUpdate other) { return; } tableUpdates_.Add(other.tableUpdates_); + if (other.RequestId != 0) { + RequestId = other.RequestId; + } + if (other.TotalHostExecutionDurationMicros != 0UL) { + TotalHostExecutionDurationMicros = other.TotalHostExecutionDurationMicros; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -2100,6 +2249,14 @@ public void MergeFrom(pb::CodedInputStream input) { tableUpdates_.AddEntriesFrom(input, _repeated_tableUpdates_codec); break; } + case 16: { + RequestId = input.ReadUInt32(); + break; + } + case 24: { + TotalHostExecutionDurationMicros = input.ReadUInt64(); + break; + } } } #endif @@ -2119,6 +2276,14 @@ public void MergeFrom(pb::CodedInputStream input) { tableUpdates_.AddEntriesFrom(ref input, _repeated_tableUpdates_codec); break; } + case 16: { + RequestId = input.ReadUInt32(); + break; + } + case 24: { + TotalHostExecutionDurationMicros = input.ReadUInt64(); + break; + } } } } @@ -2136,6 +2301,7 @@ public void MergeFrom(pb::CodedInputStream input) { //// //// `tableRowOperations` are actual modified rows. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class TableUpdate : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -2402,6 +2568,7 @@ public void MergeFrom(pb::CodedInputStream input) { //// //// - `row` is the row itself, encoded as BSATN. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class TableRowOperation : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -2652,6 +2819,7 @@ public enum OperationType { //// //// - `subscriptionUpdate` contains changes to subscribed rows. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class TransactionUpdate : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -2906,6 +3074,7 @@ public void MergeFrom(pb::CodedInputStream input) { //// To avoid data leaks, the server will NOT cache responses to messages based on UUID! //// It also will not check for duplicate IDs. They are just a way to match responses to messages. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class OneOffQuery : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -3139,6 +3308,7 @@ public void MergeFrom(pb::CodedInputStream input) { //// //// The messageId will be identical to the one sent in the original query. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class OneOffQueryResponse : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage @@ -3176,6 +3346,7 @@ public OneOffQueryResponse(OneOffQueryResponse other) : this() { messageId_ = other.messageId_; error_ = other.error_; tables_ = other.tables_.Clone(); + totalHostExecutionDurationMicros_ = other.totalHostExecutionDurationMicros_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -3220,6 +3391,18 @@ public string Error { get { return tables_; } } + /// Field number for the "total_host_execution_duration_micros" field. + public const int TotalHostExecutionDurationMicrosFieldNumber = 4; + private ulong totalHostExecutionDurationMicros_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong TotalHostExecutionDurationMicros { + get { return totalHostExecutionDurationMicros_; } + set { + totalHostExecutionDurationMicros_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -3238,6 +3421,7 @@ public bool Equals(OneOffQueryResponse other) { if (MessageId != other.MessageId) return false; if (Error != other.Error) return false; if(!tables_.Equals(other.tables_)) return false; + if (TotalHostExecutionDurationMicros != other.TotalHostExecutionDurationMicros) return false; return Equals(_unknownFields, other._unknownFields); } @@ -3248,6 +3432,7 @@ public override int GetHashCode() { if (MessageId.Length != 0) hash ^= MessageId.GetHashCode(); if (Error.Length != 0) hash ^= Error.GetHashCode(); hash ^= tables_.GetHashCode(); + if (TotalHostExecutionDurationMicros != 0UL) hash ^= TotalHostExecutionDurationMicros.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -3275,6 +3460,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteString(Error); } tables_.WriteTo(output, _repeated_tables_codec); + if (TotalHostExecutionDurationMicros != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(TotalHostExecutionDurationMicros); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -3294,6 +3483,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteString(Error); } tables_.WriteTo(ref output, _repeated_tables_codec); + if (TotalHostExecutionDurationMicros != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(TotalHostExecutionDurationMicros); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -3311,6 +3504,9 @@ public int CalculateSize() { size += 1 + pb::CodedOutputStream.ComputeStringSize(Error); } size += tables_.CalculateSize(_repeated_tables_codec); + if (TotalHostExecutionDurationMicros != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(TotalHostExecutionDurationMicros); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -3330,6 +3526,9 @@ public void MergeFrom(OneOffQueryResponse other) { Error = other.Error; } tables_.Add(other.tables_); + if (other.TotalHostExecutionDurationMicros != 0UL) { + TotalHostExecutionDurationMicros = other.TotalHostExecutionDurationMicros; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -3357,6 +3556,10 @@ public void MergeFrom(pb::CodedInputStream input) { tables_.AddEntriesFrom(input, _repeated_tables_codec); break; } + case 32: { + TotalHostExecutionDurationMicros = input.ReadUInt64(); + break; + } } } #endif @@ -3384,6 +3587,10 @@ public void MergeFrom(pb::CodedInputStream input) { tables_.AddEntriesFrom(ref input, _repeated_tables_codec); break; } + case 32: { + TotalHostExecutionDurationMicros = input.ReadUInt64(); + break; + } } } } @@ -3394,6 +3601,7 @@ public void MergeFrom(pb::CodedInputStream input) { /// //// A table included as part of a one-off query. /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class OneOffTable : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage diff --git a/sdks/csharp/src/ClientApiExtensions.cs b/sdks/csharp/src/ClientApiExtensions.cs index f4445af11bc..5f56bf2c3d6 100644 --- a/sdks/csharp/src/ClientApiExtensions.cs +++ b/sdks/csharp/src/ClientApiExtensions.cs @@ -2,6 +2,6 @@ { public partial class FunctionCall { - public SpacetimeDB.ReducerEventBase CallInfo { get; set; } + public SpacetimeDB.ReducerEventBase? CallInfo { get; set; } } -} \ No newline at end of file +} diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index fb66925f2b3..f4f67d36484 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -1,68 +1,28 @@ using System; -using System.Collections.Concurrent; +using System.Collections; using System.Collections.Generic; -using System.Reflection; -using SpacetimeDB.SATS; using System.Linq; +using SpacetimeDB.BSATN; +using Google.Protobuf; namespace SpacetimeDB { public class ClientCache { - public class TableCache + public interface ITableCache : IEnumerable> { - private readonly Type clientTableType; - private readonly AlgebraicType rowSchema; - - // The function to use for decoding a type value - private Func decoderFunc; - - // Maps from primary key to type value - public readonly Dictionary entries = new(ByteArrayComparer.Instance); - - public Type ClientTableType - { - get => clientTableType; - } - - public Action InternalValueInsertedCallback; - public Action InternalValueDeletedCallback; - public Action InsertCallback; - public Action BeforeDeleteCallback; - public Action DeleteCallback; - public Action UpdateCallback; - public Func GetPrimaryKeyValueFunc; - - public AlgebraicType RowSchema - { - get => rowSchema; - } + Type ClientTableType { get; } + bool InsertEntry(byte[] rowBytes, IDatabaseTable value); + bool DeleteEntry(byte[] rowBytes); + IDatabaseTable DecodeValue(ByteString bytes); + } - public TableCache(Type clientTableType, AlgebraicType rowSchema, Func decoderFunc) - { - this.clientTableType = clientTableType; + public class TableCache : ITableCache + where T: IDatabaseTable, IStructuralReadWrite, new() + { + public Type ClientTableType => typeof(T); - this.rowSchema = rowSchema; - this.decoderFunc = decoderFunc; - InternalValueInsertedCallback = (Action)clientTableType.GetMethod("InternalOnValueInserted", BindingFlags.NonPublic | BindingFlags.Static)?.CreateDelegate(typeof(Action)); - InternalValueDeletedCallback = (Action)clientTableType.GetMethod("InternalOnValueDeleted", BindingFlags.NonPublic | BindingFlags.Static)?.CreateDelegate(typeof(Action)); - InsertCallback = (Action)clientTableType.GetMethod("OnInsertEvent")?.CreateDelegate(typeof(Action)); - BeforeDeleteCallback = (Action)clientTableType.GetMethod("OnBeforeDeleteEvent")?.CreateDelegate(typeof(Action)); - DeleteCallback = (Action)clientTableType.GetMethod("OnDeleteEvent")?.CreateDelegate(typeof(Action)); - UpdateCallback = (Action)clientTableType.GetMethod("OnUpdateEvent")?.CreateDelegate(typeof(Action)); - GetPrimaryKeyValueFunc = (Func)clientTableType.GetMethod("GetPrimaryKeyValue", BindingFlags.NonPublic | BindingFlags.Static) - ?.CreateDelegate(typeof(Func)); - } - - /// - /// Decodes the given AlgebraicValue into the out parameter `obj`. - /// - /// The AlgebraicValue to decode. - /// The domain object for `value` - public void SetAndForgetDecodedValue(AlgebraicValue value, out object obj) - { - obj = decoderFunc(value); - } + public static readonly Dictionary Entries = new (ByteArrayComparer.Instance); /// /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. @@ -70,7 +30,7 @@ public void SetAndForgetDecodedValue(AlgebraicValue value, out object obj) /// The BSATN encoded bytes of the row to retrieve. /// The parsed row encoded by the rowBytes. /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. - public bool InsertEntry(byte[] rowBytes, object value) => entries.TryAdd(rowBytes, value); + public bool InsertEntry(byte[] rowBytes, IDatabaseTable value) => Entries.TryAdd(rowBytes, (T)value); /// /// Deletes a value from the table. @@ -79,7 +39,7 @@ public void SetAndForgetDecodedValue(AlgebraicValue value, out object obj) /// True if and only if the value was previously resident and has been deleted. public bool DeleteEntry(byte[] rowBytes) { - if (entries.Remove(rowBytes)) + if (Entries.Remove(rowBytes)) { return true; } @@ -88,30 +48,28 @@ public bool DeleteEntry(byte[] rowBytes) return false; } - public object? GetPrimaryKeyValue(object row) - { - return GetPrimaryKeyValueFunc?.Invoke(row); - } + // The function to use for decoding a type value. + public IDatabaseTable DecodeValue(ByteString bytes) => BSATNHelpers.FromProtoBytes(bytes); + + public IEnumerator> GetEnumerator() => Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)).GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } - private readonly ConcurrentDictionary tables = - new ConcurrentDictionary(); + private readonly Dictionary tables = new(); - public void AddTable(Type clientTableType, AlgebraicType tableRowDef, Func decodeFunc) + public void AddTable() + where T: IDatabaseTable, IStructuralReadWrite, new() { - string name = clientTableType.Name; + string name = typeof(T).Name; - if (tables.TryGetValue(name, out _)) + if (!tables.TryAdd(name, new TableCache())) { Logger.LogError($"Table with name already exists: {name}"); - return; } - - // Initialize this table - tables[name] = new TableCache(clientTableType, tableRowDef, decodeFunc); } - public TableCache? GetTable(string name) + public ITableCache? GetTable(string name) { if (tables.TryGetValue(name, out var table)) { @@ -122,13 +80,6 @@ public void AddTable(Type clientTableType, AlgebraicType tableRowDef, Func GetObjects(string name) - { - return GetTable(name)?.entries.Values ?? Enumerable.Empty(); - } - - public int Count(string name) => GetTable(name)?.entries.Count ?? 0; - - public IEnumerable GetTables() => tables.Values; + public IEnumerable GetTables() => tables.Values; } } diff --git a/sdks/csharp/src/IDatabaseTable.cs b/sdks/csharp/src/IDatabaseTable.cs index 2df6585aeff..57435bfde8f 100644 --- a/sdks/csharp/src/IDatabaseTable.cs +++ b/sdks/csharp/src/IDatabaseTable.cs @@ -1,7 +1,82 @@ -using System.Collections; +using System; using System.Collections.Generic; +using System.Linq; +using SpacetimeDB.BSATN; namespace SpacetimeDB { - public interface IDatabaseTable { } -} \ No newline at end of file + public interface IDatabaseTable + { + void InternalOnValueInserted(); + void InternalOnValueDeleted(); + void OnInsertEvent(ClientApi.Event? dbEvent); + void OnBeforeDeleteEvent(ClientApi.Event? dbEvent); + void OnDeleteEvent(ClientApi.Event? dbEvent); + } + + public abstract class DatabaseTable : IDatabaseTable + where T : DatabaseTable, IStructuralReadWrite, new() + where ReducerEvent : ReducerEventBase + { + public virtual void InternalOnValueInserted() { } + + public virtual void InternalOnValueDeleted() { } + + public static IEnumerable Iter() + { + return ClientCache.TableCache.Entries.Values; + } + + public static IEnumerable Query(Func filter) + { + return Iter().Where(filter); + } + + public static int Count() + { + return ClientCache.TableCache.Entries.Count; + } + + public delegate void InsertEventHandler(T insertedValue, ReducerEvent? dbEvent); + public delegate void DeleteEventHandler(T deletedValue, ReducerEvent? dbEvent); + public static event InsertEventHandler? OnInsert; + public static event DeleteEventHandler? OnBeforeDelete; + public static event DeleteEventHandler? OnDelete; + + public void OnInsertEvent(ClientApi.Event? dbEvent) + { + OnInsert?.Invoke((T)this, (ReducerEvent?)dbEvent?.FunctionCall.CallInfo); + } + + public void OnBeforeDeleteEvent(ClientApi.Event? dbEvent) + { + OnBeforeDelete?.Invoke((T)this, (ReducerEvent?)dbEvent?.FunctionCall.CallInfo); + } + + public void OnDeleteEvent(ClientApi.Event? dbEvent) + { + OnDelete?.Invoke((T)this, (ReducerEvent?)dbEvent?.FunctionCall.CallInfo); + } + } + + public interface IDatabaseTableWithPrimaryKey : IDatabaseTable + { + void OnUpdateEvent(IDatabaseTableWithPrimaryKey newValue, ClientApi.Event? dbEvent); + object GetPrimaryKeyValue(); + } + + public abstract class DatabaseTableWithPrimaryKey : DatabaseTable, IDatabaseTableWithPrimaryKey + where T : DatabaseTableWithPrimaryKey, IStructuralReadWrite, new() + where ReducerEvent : ReducerEventBase + { + public abstract object GetPrimaryKeyValue(); + + public delegate void UpdateEventHandler(T oldValue, T newValue, ReducerEvent? dbEvent); + public static event UpdateEventHandler? OnUpdate; + + public void OnUpdateEvent(IDatabaseTableWithPrimaryKey newValue, ClientApi.Event? dbEvent) + { + OnUpdate?.Invoke((T)this, (T)newValue, (ReducerEvent?)dbEvent?.FunctionCall.CallInfo); + } + } +} diff --git a/sdks/csharp/src/Identity.cs b/sdks/csharp/src/Identity.cs index 1a808eabebb..c0ad8d7676f 100644 --- a/sdks/csharp/src/Identity.cs +++ b/sdks/csharp/src/Identity.cs @@ -1,62 +1,45 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using SpacetimeDB.SATS; +using System.IO; +using SpacetimeDB.BSATN; namespace SpacetimeDB { - public struct Identity : IEquatable + public readonly struct Identity : IEquatable { - private byte[] bytes; public const int SIZE = 32; - public byte[] Bytes => bytes; + public readonly byte[] Bytes; - public static AlgebraicType GetAlgebraicType() + private Identity(byte[] bytes) => Bytes = bytes; + + public readonly struct BSATN : IReadWrite { - return new AlgebraicType - { - type = AlgebraicType.Type.Builtin, - builtin = new BuiltinType - { - type = BuiltinType.Type.Array, - arrayType = new AlgebraicType + public Identity Read(BinaryReader reader) => From(ByteArray.Instance.Read(reader)); + public void Write(BinaryWriter writer, Identity value) => ByteArray.Instance.Write(writer, value.Bytes); + + public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => + new AlgebraicType.Product( + new AggregateElement[] { - type = AlgebraicType.Type.Builtin, - builtin = new BuiltinType - { - type = BuiltinType.Type.U8 - } + new("__identity_bytes", ByteArray.Instance.GetAlgebraicType(registrar)) } - } - }; + ); } - public static explicit operator Identity(AlgebraicValue v) => new Identity - { - bytes = v.AsBytes(), - }; - - public static Identity From(byte[] bytes) - { + public static Identity From(byte[] bytes) => // TODO: should we validate length here? - return new Identity - { - bytes = bytes, - }; - } + new(bytes); - public bool Equals(Identity other) => ByteArrayComparer.Instance.Equals(bytes, other.bytes); + public bool Equals(Identity other) => ByteArrayComparer.Instance.Equals(Bytes, other.Bytes); - public override bool Equals(object o) => o is Identity other && Equals(other); + public override bool Equals(object? o) => o is Identity other && Equals(other); public static bool operator ==(Identity a, Identity b) => a.Equals(b); public static bool operator !=(Identity a, Identity b) => !a.Equals(b); - public override int GetHashCode() => ByteArrayComparer.Instance.GetHashCode(bytes); + public override int GetHashCode() => ByteArrayComparer.Instance.GetHashCode(Bytes); - public override string ToString() => ByteArrayComparer.ToHexString(bytes); + public override string ToString() => ByteArrayComparer.ToHexString(Bytes); } } diff --git a/sdks/csharp/src/NetworkManager.cs b/sdks/csharp/src/NetworkManager.cs deleted file mode 100644 index a837cdd65c6..00000000000 --- a/sdks/csharp/src/NetworkManager.cs +++ /dev/null @@ -1,45 +0,0 @@ -/* SpacetimeDB for Unity - * * This class is only used in Unity projects. Attach this to a gameobject in your scene to use SpacetimeDB. - * * - */ -#if UNITY_5_3_OR_NEWER -using UnityEngine; - -namespace SpacetimeDB -{ - // This is an optional helper class to store your auth token in PlayerPrefs - // Override GetTokenKey() if you want to use a player pref key specific to your game - public static class AuthToken - { - public static string Token => PlayerPrefs.GetString(GetTokenKey()); - - public static void SaveToken(string token) - { - PlayerPrefs.SetString(GetTokenKey(), token); - } - - public static string GetTokenKey() - { - var key = "spacetimedb.identity_token"; -#if UNITY_EDITOR - // Different editors need different keys - key += $" - {Application.dataPath}"; -#endif - return key; - } - } - - public class NetworkManager : MonoBehaviour - { - private void OnDestroy() - { - SpacetimeDBClient.instance.Close(); - } - - private void Update() - { - SpacetimeDBClient.instance.Update(); - } - } -} -#endif diff --git a/sdks/csharp/src/ReducerExtensions.cs b/sdks/csharp/src/ReducerExtensions.cs deleted file mode 100644 index a86e364963a..00000000000 --- a/sdks/csharp/src/ReducerExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace SpacetimeDB -{ - public class ReducerClassAttribute : Attribute - { - } - - public class ReducerCallbackAttribute : Attribute - { - public string FunctionName { get; set; } - } - - public class DeserializeEventAttribute : Attribute - { - public string FunctionName { get; set; } - } -} diff --git a/sdks/csharp/src/ReducerMismatchException.cs b/sdks/csharp/src/ReducerMismatchException.cs deleted file mode 100644 index 799d46ff501..00000000000 --- a/sdks/csharp/src/ReducerMismatchException.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SpacetimeDB -{ - public class ReducerMismatchException : Exception - { - public ReducerMismatchException(string originalReducerName, string attemptedConversionReducerName) - : base($"Cannot cast agruments from {originalReducerName} reducer call into {attemptedConversionReducerName} reducer arguments") - { - } - } -} diff --git a/sdks/csharp/src/SATS/AlgebraicType.cs b/sdks/csharp/src/SATS/AlgebraicType.cs deleted file mode 100644 index d499a11de89..00000000000 --- a/sdks/csharp/src/SATS/AlgebraicType.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Numerics; -using System.Runtime.InteropServices; - -namespace SpacetimeDB.SATS -{ - public class SumType - { - public List variants; - - public SumType() - { - variants = new List(); - } - - // TODO(jdetter): Perhaps not needed? - public SumType NewUnnamed() - { - var s = new SumType - { - variants = variants.Select(a => new SumTypeVariant(null, a.algebraicType)).ToList() - }; - return s; - } - } - - public struct SumTypeVariant - { - public string name; - public AlgebraicType algebraicType; - - public SumTypeVariant(string name, AlgebraicType algebraicType) - { - this.name = name; - this.algebraicType = algebraicType; - } - } - - public class ProductType - { - public List elements; - - public ProductType() - { - elements = new List(); - } - } - - public struct ProductTypeElement - { - public string name; - public AlgebraicType algebraicType; - - public ProductTypeElement(string name, AlgebraicType algebraicType) - { - this.name = name; - this.algebraicType = algebraicType; - } - - public ProductTypeElement(AlgebraicType algebraicType) - { - name = null; - this.algebraicType = algebraicType; - } - } - - public struct MapType - { - public AlgebraicType keyType; - public AlgebraicType valueType; - } - - public class BuiltinType - { - public enum Type - { - Bool, - I8, - U8, - I16, - U16, - I32, - U32, - I64, - U64, - I128, - U128, - F32, - F64, - String, - Array, - Map - } - - public Type type; - - public AlgebraicType arrayType; - public MapType mapType; - } - - public class AlgebraicType - { - public enum Type - { - Sum, - Product, - Builtin, - TypeRef, - None, - } - - public Type type; - private object type_; - - public SumType sum { - get { return type == Type.Sum ? (SumType)type_ : null; } - set { - type_ = value; - type = value == null ? Type.None : Type.Sum; - } - } - - public ProductType product { - get { return type == Type.Product ? (ProductType)type_ : null; } - set { - type_ = value; - type = value == null ? Type.None : Type.Product; - } - } - - public BuiltinType builtin { - get { return type == Type.Builtin ? (BuiltinType)type_ : null; } - set { - type_ = value; - type = value == null ? Type.None : Type.Builtin; - } - } - - public int typeRef { - get { return type == Type.TypeRef ? (int)type_ : -1; } - set { - type_ = value; - type = value == -1 ? Type.None : Type.TypeRef; - } - } - - public static AlgebraicType CreateProductType(IEnumerable elements) - { - return new AlgebraicType - { - type = Type.Product, - product = new ProductType - { - elements = elements.ToList() - } - }; - } - - public static AlgebraicType CreateSumType(IEnumerable variants) - { - return new AlgebraicType - { - type = Type.Sum, - sum = new SumType - { - variants = variants.ToList(), - } - }; - } - - public static AlgebraicType CreateArrayType(AlgebraicType elementType) { - return new AlgebraicType - { - type = Type.Builtin, - builtin = new BuiltinType - { - type = BuiltinType.Type.Array, - arrayType = elementType - } - }; - } - - public static AlgebraicType CreatePrimitiveType(BuiltinType.Type type) { - return new AlgebraicType - { - type = Type.Builtin, - builtin = new BuiltinType - { - type = type, - } - }; - } - - } -} \ No newline at end of file diff --git a/sdks/csharp/src/SATS/AlgebraicValue.cs b/sdks/csharp/src/SATS/AlgebraicValue.cs deleted file mode 100644 index 594d15a6022..00000000000 --- a/sdks/csharp/src/SATS/AlgebraicValue.cs +++ /dev/null @@ -1,479 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace SpacetimeDB.SATS -{ - public struct BuiltinValue - { - private object value; - - public bool AsBool() => (bool)value; - public sbyte AsI8() => (sbyte)value; - public byte AsU8() => (byte)value; - public short AsI16() => (short)value; - public ushort AsU16() => (ushort)value; - public int AsI32() => (int)value; - public uint AsU32() => (uint)value; - public long AsI64() => (long)value; - public ulong AsU64() => (ulong)value; - public byte[] AsI128() => (byte[])value; - public byte[] AsU128() => (byte[])value; - public float AsF32() => (float)value; - public double AsF64() => (double)value; - public byte[] AsBytes() => (byte[])value; - public string AsString() => (string)value; - public List AsArray() => (List)value; - public Dictionary AsMap() => (Dictionary)value; - - public static BuiltinValue CreateBool(bool value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateI8(sbyte value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateU8(byte value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateI16(short value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateU16(ushort value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateI32(int value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateU32(uint value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateI64(long value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateU64(ulong value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateI128(byte[] value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateU128(byte[] value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateF32(float value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateF64(double value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateString(string value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateBytes(byte[] value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateArray(List value) => new BuiltinValue { value = value }; - public static BuiltinValue CreateMap(Dictionary value) => new BuiltinValue { value = value }; - - public void Serialize(BuiltinType type, BinaryWriter writer) - { - void WriteByteBuffer(byte[] buf) - { - if (buf.LongLength > uint.MaxValue) - { - throw new Exception("Serializing a buffer that is too large for SATS."); - } - - writer.Write((uint)buf.LongLength); - writer.Write(buf); - } - - switch (type.type) - { - case BuiltinType.Type.Bool: - writer.Write(AsBool()); - break; - case BuiltinType.Type.I8: - writer.Write(AsI8()); - break; - case BuiltinType.Type.U8: - writer.Write(AsU8()); - break; - case BuiltinType.Type.I16: - writer.Write(AsI16()); - break; - case BuiltinType.Type.U16: - writer.Write(AsU16()); - break; - case BuiltinType.Type.I32: - writer.Write(AsI32()); - break; - case BuiltinType.Type.U32: - writer.Write(AsU32()); - break; - case BuiltinType.Type.I64: - writer.Write(AsI64()); - break; - case BuiltinType.Type.U64: - writer.Write(AsU64()); - break; - case BuiltinType.Type.I128: - writer.Write(AsI128()); - break; - case BuiltinType.Type.U128: - writer.Write(AsU128()); - break; - case BuiltinType.Type.F32: - writer.Write(AsF32()); - break; - case BuiltinType.Type.F64: - writer.Write(AsF64()); - break; - case BuiltinType.Type.String: - WriteByteBuffer(System.Text.Encoding.UTF8.GetBytes((string)value)); - break; - case BuiltinType.Type.Array: - if (type.arrayType.type == AlgebraicType.Type.Builtin && - type.arrayType.builtin.type == BuiltinType.Type.U8) - { - WriteByteBuffer(AsBytes()); - break; - } - - var array = AsArray(); - writer.Write(array.Count); - foreach (var entry in array) - { - entry.Serialize(type.arrayType, writer); - } - break; - case BuiltinType.Type.Map: - throw new NotImplementedException(); - } - } - - public static BuiltinValue Deserialize(BuiltinType type, BinaryReader reader) - { - byte[] ReadByteArray() - { - var len = reader.ReadUInt32(); - if (len > int.MaxValue) - { - var arrays = new List(); - long read = 0; - while (read < len) - { - var remaining = len - read; - var readResult = reader.ReadBytes(remaining > int.MaxValue ? int.MaxValue : (int)remaining); - arrays.Add(readResult); - read += readResult.Length; - } - - var result = new byte[len]; - long pos = 0; - foreach (var array in arrays) - { - Array.Copy(array, 0, result, pos, array.LongLength); - pos += array.LongLength; - } - - return result; - } - - return reader.ReadBytes((int)len); - } - - switch (type.type) - { - case BuiltinType.Type.Bool: - return CreateBool(reader.ReadByte() != 0); - case BuiltinType.Type.I8: - return CreateI8(reader.ReadSByte()); - case BuiltinType.Type.U8: - return CreateU8(reader.ReadByte()); - case BuiltinType.Type.I16: - return CreateI16(reader.ReadInt16()); - case BuiltinType.Type.U16: - return CreateU16(reader.ReadUInt16()); - case BuiltinType.Type.I32: - return CreateI32(reader.ReadInt32()); - case BuiltinType.Type.U32: - return CreateU32(reader.ReadUInt32()); - case BuiltinType.Type.I64: - return CreateI64(reader.ReadInt64()); - case BuiltinType.Type.U64: - return CreateU64(reader.ReadUInt64()); - case BuiltinType.Type.I128: - return CreateI128(reader.ReadBytes(16)); - case BuiltinType.Type.U128: - return CreateU128(reader.ReadBytes(16)); - case BuiltinType.Type.F32: - return CreateF32(reader.ReadSingle()); - case BuiltinType.Type.F64: - return CreateF64(reader.ReadDouble()); - case BuiltinType.Type.String: - return CreateString(System.Text.Encoding.UTF8.GetString(ReadByteArray())); - case BuiltinType.Type.Array: - if (type.arrayType.type == AlgebraicType.Type.Builtin && - type.arrayType.builtin.type == BuiltinType.Type.U8) - { - return CreateBytes(ReadByteArray()); - } - - var length = reader.ReadInt32(); - var arrayResult = new List(); - for (var x = 0; x < length; x++) - { - arrayResult.Add(AlgebraicValue.Deserialize(type.arrayType, reader)); - } - - return CreateArray(arrayResult); - case BuiltinType.Type.Map: - { - var len = reader.ReadUInt32(); - var mapResult = new Dictionary(); - for (var x = 0; x < len; x++) - { - var key = AlgebraicValue.Deserialize(type.mapType.keyType, reader); - var value = AlgebraicValue.Deserialize(type.mapType.valueType, reader); - mapResult.Add(key, value); - } - - return CreateMap(mapResult); - } - default: - throw new NotImplementedException(); - } - } - - public static bool Compare(BuiltinType t, BuiltinValue v1, BuiltinValue v2) - { - switch (t.type) - { - case BuiltinType.Type.Bool: - return v1.AsBool() == v2.AsBool(); - case BuiltinType.Type.U8: - return v1.AsU8() == v2.AsU8(); - case BuiltinType.Type.I8: - return v1.AsI8() == v2.AsI8(); - case BuiltinType.Type.U16: - return v1.AsU16() == v2.AsU16(); - case BuiltinType.Type.I16: - return v1.AsI16() == v2.AsI16(); - case BuiltinType.Type.U32: - return v1.AsU32() == v2.AsU32(); - case BuiltinType.Type.I32: - return v1.AsI32() == v2.AsI32(); - case BuiltinType.Type.U64: - return v1.AsU64() == v2.AsU64(); - case BuiltinType.Type.I64: - return v1.AsI64() == v2.AsI64(); - case BuiltinType.Type.U128: - case BuiltinType.Type.I128: - case BuiltinType.Type.F32: - case BuiltinType.Type.F64: - case BuiltinType.Type.Map: - throw new NotImplementedException(); - case BuiltinType.Type.String: - return v1.AsString() == v2.AsString(); - case BuiltinType.Type.Array: - if (t.arrayType.type == AlgebraicType.Type.Builtin && - t.arrayType.builtin.type == BuiltinType.Type.U8) - { - var arr1 = v1.AsBytes(); - var arr2 = v2.AsBytes(); - - if (arr1.Length != arr2.Length) - { - return false; - } - - for (var i = 0; i < arr1.Length; i++) - { - if (arr1[i] != arr2[i]) - { - return false; - } - } - - return true; - } - - var list1 = v1.AsArray(); - var list2 = v2.AsArray(); - if (list1.Count != list2.Count) - { - return false; - } - - for (var i = 0; i < list1.Count; i++) - { - if (!AlgebraicValue.Compare(t.arrayType, list1[i], list2[i])) - { - return false; - } - } - return true; - default: - throw new NotImplementedException(); - } - } - } - - public class SumValue - { - public byte tag; - public AlgebraicValue value; - - private SumValue() - { - } - - public SumValue(byte tag, AlgebraicValue value) - { - this.tag = tag; - this.value = value; - } - - public static SumValue Deserialize(SumType type, BinaryReader reader) - { - var result = new SumValue(); - result.tag = reader.ReadByte(); - result.value = AlgebraicValue.Deserialize(type.variants[result.tag].algebraicType, reader); - return result; - } - - public void Serialize(SumType type, BinaryWriter writer) - { - writer.Write(tag); - value.Serialize(type.variants[tag].algebraicType, writer); - } - - public static bool Compare(SumType t, SumValue v1, SumValue v2) - { - if (v1.tag != v2.tag) - { - return false; - } - - return AlgebraicValue.Compare(t.variants[v1.tag].algebraicType, v1.value, v2.value); - } - } - - public class ProductValue - { - public List elements; - - public ProductValue() - { - elements = new List(); - } - - public void Serialize(ProductType type, BinaryWriter writer) - { - writer.Write((uint)elements.Count); - for (var x = 0; x < elements.Count; x++) - { - elements[x].Serialize(type.elements[x].algebraicType, writer); - } - } - - public static ProductValue Deserialize(ProductType type, BinaryReader reader) - { - var result = new ProductValue(); - for (var x = 0; x < type.elements.Count; x++) - { - result.elements.Add(AlgebraicValue.Deserialize(type.elements[x].algebraicType, reader)); - } - - return result; - } - - public static bool Compare(ProductType type, ProductValue v1, ProductValue v2) - { - if (v1.elements.Count != v2.elements.Count) - { - return false; - } - - for (var i = 0; i < type.elements.Count; i++) - { - if (!AlgebraicValue.Compare(type.elements[i].algebraicType, v1.elements[i], v2.elements[i])) - { - return false; - } - } - - return true; - } - } - - public class AlgebraicValue - { - public SumValue sum; - public ProductValue product; - public BuiltinValue builtin; - - public bool AsBool() => builtin.AsBool(); - public sbyte AsI8() => builtin.AsI8(); - public byte AsU8() => builtin.AsU8(); - public short AsI16() => builtin.AsI16(); - public ushort AsU16() => builtin.AsU16(); - public int AsI32() => builtin.AsI32(); - public uint AsU32() => builtin.AsU32(); - public long AsI64() => builtin.AsI64(); - public ulong AsU64() => builtin.AsU64(); - public byte[] AsI128() => builtin.AsI128(); - public byte[] AsU128() => builtin.AsU128(); - public float AsF32() => builtin.AsF32(); - public double AsF64() => builtin.AsF64(); - public string AsString() => builtin.AsString(); - public byte[] AsBytes() => builtin.AsBytes(); - public List AsArray() => builtin.AsArray(); - public Dictionary AsMap() => builtin.AsMap(); - public static AlgebraicValue CreateBool(bool v) => new AlgebraicValue { builtin = BuiltinValue.CreateBool(v) }; - public static AlgebraicValue CreateI8(sbyte v) => new AlgebraicValue { builtin = BuiltinValue.CreateI8(v) }; - public static AlgebraicValue CreateU8(byte v) => new AlgebraicValue { builtin = BuiltinValue.CreateU8(v) }; - public static AlgebraicValue CreateI16(short v) => new AlgebraicValue { builtin = BuiltinValue.CreateI16(v) }; - public static AlgebraicValue CreateU16(ushort v) => new AlgebraicValue { builtin = BuiltinValue.CreateU16(v) }; - public static AlgebraicValue CreateI32(int v) => new AlgebraicValue { builtin = BuiltinValue.CreateI32(v) }; - public static AlgebraicValue CreateU32(uint v) => new AlgebraicValue { builtin = BuiltinValue.CreateU32(v) }; - public static AlgebraicValue CreateI64(long v) => new AlgebraicValue { builtin = BuiltinValue.CreateI64(v) }; - public static AlgebraicValue CreateU64(ulong v) => new AlgebraicValue { builtin = BuiltinValue.CreateU64(v) }; - public static AlgebraicValue CreateI128(byte[] v) => new AlgebraicValue { builtin = BuiltinValue.CreateI128(v) }; - public static AlgebraicValue CreateU128(byte[] v) => new AlgebraicValue { builtin = BuiltinValue.CreateU128(v) }; - public static AlgebraicValue CreateF32(float v) => new AlgebraicValue { builtin = BuiltinValue.CreateF32(v) }; - public static AlgebraicValue CreateF64(double v) => new AlgebraicValue { builtin = BuiltinValue.CreateF64(v) }; - public static AlgebraicValue CreateString(string v) => new AlgebraicValue { builtin = BuiltinValue.CreateString(v) }; - public static AlgebraicValue CreateBytes(byte[] v) => new AlgebraicValue { builtin = BuiltinValue.CreateBytes(v) }; - public static AlgebraicValue CreateArray(List v) => new AlgebraicValue { builtin = BuiltinValue.CreateArray(v) }; - public static AlgebraicValue CreateMap(Dictionary v) => new AlgebraicValue { builtin = BuiltinValue.CreateMap(v) }; - - public BuiltinValue AsBuiltInValue() => builtin; - public ProductValue AsProductValue() => product; - public SumValue AsSumValue() => sum; - - public static AlgebraicValue Create(BuiltinValue value) => new AlgebraicValue { builtin = value }; - public static AlgebraicValue Create(ProductValue value) => new AlgebraicValue { product = value }; - public static AlgebraicValue Create(SumValue value) => new AlgebraicValue { sum = value }; - - public static bool Compare(AlgebraicType t, AlgebraicValue v1, AlgebraicValue v2) - { - switch (t.type) - { - case AlgebraicType.Type.Builtin: - return BuiltinValue.Compare(t.builtin, v1.builtin, v2.builtin); - case AlgebraicType.Type.Sum: - return SumValue.Compare(t.sum, v1.sum, v2.sum); - case AlgebraicType.Type.Product: - return ProductValue.Compare(t.product, v1.product, v2.product); - case AlgebraicType.Type.TypeRef: - case AlgebraicType.Type.None: - default: - throw new NotImplementedException(); - } - } - - public static AlgebraicValue Deserialize(AlgebraicType type, BinaryReader reader) - { - switch (type.type) - { - case AlgebraicType.Type.Builtin: - return Create(BuiltinValue.Deserialize(type.builtin, reader)); - case AlgebraicType.Type.Product: - return Create(ProductValue.Deserialize(type.product, reader)); - case AlgebraicType.Type.Sum: - return Create(SumValue.Deserialize(type.sum, reader)); - default: - throw new NotImplementedException(); - } - } - - public void Serialize(AlgebraicType type, BinaryWriter writer) - { - switch (type.type) - { - case AlgebraicType.Type.Builtin: - builtin.Serialize(type.builtin, writer); - break; - case AlgebraicType.Type.Product: - product.Serialize(type.product, writer); - break; - case AlgebraicType.Type.Sum: - sum.Serialize(type.sum, writer); - break; - default: - throw new NotImplementedException(); - } - } - } -} diff --git a/sdks/csharp/src/SATS/Typespace.cs b/sdks/csharp/src/SATS/Typespace.cs deleted file mode 100644 index 0604ee9d1bf..00000000000 --- a/sdks/csharp/src/SATS/Typespace.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections; -using System.Collections.Generic; - -namespace SpacetimeDB.SATS -{ - public class Typespace - { - public int rootRef; - public List types; - - public Typespace() - { - rootRef = 0; - types = new List(); - } - - public void Add(AlgebraicType type) - { - types.Add(type); - } - - public AlgebraicType GetRoot() => types[rootRef]; - } - - public struct GenCtx - { - public Typespace typespace; - public List names; - } -} \ No newline at end of file diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 00984b63b51..ca7f8710cea 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -5,36 +5,25 @@ using System.IO.Compression; using System.Linq; using System.Net.WebSockets; -using System.Reflection; -using System.Text; using System.Threading; using System.Threading.Tasks; using ClientApi; -using Newtonsoft.Json; -using SpacetimeDB.SATS; +using SpacetimeDB.BSATN; using Thread = System.Threading.Thread; +using Google.Protobuf; +using Event = ClientApi.Event; namespace SpacetimeDB { - public class SpacetimeDBClient + public abstract class SpacetimeDBClientBase + where ReducerEvent : ReducerEventBase { - public class ReducerCallRequest - { - public string fn; - public object[] args; - } - - public class SubscriptionRequest - { - public string subscriptionQuery; - } - struct DbValue { - public object value; + public IDatabaseTable value; public byte[] bytes; - public DbValue(object value, byte[] bytes) + public DbValue(IDatabaseTable value, byte[] bytes) { this.value = value; this.bytes = bytes; @@ -43,7 +32,7 @@ public DbValue(object value, byte[] bytes) struct DbOp { - public ClientCache.TableCache table; + public ClientCache.ITableCache table; public DbValue? delete; public DbValue? insert; } @@ -51,92 +40,64 @@ struct DbOp /// /// Called when a connection is established to a spacetimedb instance. /// - public event Action onConnect; + public event Action? onConnect; /// /// Called when a connection attempt fails. /// - public event Action onConnectError; + public event Action? onConnectError; /// /// Called when an exception occurs when sending a message. /// - public event Action onSendError; + public event Action? onSendError; /// /// Called when a connection that was established has disconnected. /// - public event Action onDisconnect; + public event Action? onDisconnect; /// /// Invoked when a subscription is about to start being processed. This is called even before OnBeforeDelete. /// - public event Action onBeforeSubscriptionApplied; + public event Action? onBeforeSubscriptionApplied; /// /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. /// - public event Action onSubscriptionApplied; + public event Action? onSubscriptionApplied; /// /// Invoked when a reducer is returned with an error and has no client-side handler. /// - public event Action onUnhandledReducerError; + public event Action? onUnhandledReducerError; /// /// Called when we receive an identity from the server /// - public event Action onIdentityReceived; + public event Action? onIdentityReceived; /// /// Invoked when an event message is received or at the end of a transaction update. /// - public event Action onEvent; + public event Action? onEvent; public readonly Address clientAddress = Address.Random(); + public Identity clientIdentity { get; private set; } private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; - public static ClientCache clientDB; - - private static Dictionary> reducerEventCache = new(); + protected readonly ClientCache clientDB = new(); - private static Dictionary> deserializeEventCache = new(); + protected abstract ReducerEvent ReducerEventFromDbEvent(ClientApi.Event dbEvent); - private static Dictionary> waitingOneOffQueries = new(); + private readonly Dictionary> waitingOneOffQueries = new(); private bool isClosing; - private Thread networkMessageProcessThread; - private Thread stateDiffProcessThread; - - public static readonly SpacetimeDBClient instance = new(); - - public Type FindReducerType() - { - // Get all loaded assemblies - Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - - // Iterate over each assembly and search for the type - foreach (Assembly assembly in assemblies) - { - // Get all types in the assembly - Type[] types = assembly.GetTypes(); - - // Search for the class with the attribute ReducerClass - foreach (Type type in types) - { - if (type.GetCustomAttribute() != null) - { - return type; - } - } - } - - // If the type is not found in any assembly, return null or throw an exception - return null; - } + private readonly Thread networkMessageProcessThread; + public readonly Stats stats = new(); - protected SpacetimeDBClient() + protected SpacetimeDBClientBase() { var options = new SpacetimeDB.ConnectOptions { @@ -151,80 +112,37 @@ protected SpacetimeDBClient() webSocket.OnConnectError += (a, b) => onConnectError?.Invoke(a, b); webSocket.OnSendError += a => onSendError?.Invoke(a); - clientDB = new ClientCache(); - - var type = typeof(IDatabaseTable); - var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes()) - .Where(p => type.IsAssignableFrom(p)); - foreach (var @class in types) - { - if (!@class.IsClass) - { - continue; - } - - var algebraicTypeFunc = @class.GetMethod("GetAlgebraicType", BindingFlags.Static | BindingFlags.Public); - var algebraicValue = algebraicTypeFunc!.Invoke(null, null) as AlgebraicType; - var conversionFunc = @class.GetMethods() - .FirstOrDefault(a => a.Name == "op_Explicit" && - a.GetParameters().Length > 0 && - a.GetParameters()[0].ParameterType == - typeof(AlgebraicValue)); - clientDB.AddTable(@class, algebraicValue, - a => { return conversionFunc!.Invoke(null, new object[] { a }); }); - } - - var reducerType = FindReducerType(); - if (reducerType != null) - { - // cache all our reducer events by their function name - foreach (var methodInfo in reducerType.GetMethods()) - { - if (methodInfo.GetCustomAttribute() is - { } reducerEvent) - { - reducerEventCache.Add(reducerEvent.FunctionName, - (Func)methodInfo.CreateDelegate( - typeof(Func))); - } - - if (methodInfo.GetCustomAttribute() is - { } deserializeEvent) - { - deserializeEventCache.Add(deserializeEvent.FunctionName, - (Action)methodInfo.CreateDelegate(typeof(Action))); - } - } - } - else - { - Logger.LogError($"Could not find reducer type. Have you run spacetime generate?"); - } - - _preProcessCancellationToken = _preProcessCancellationTokenSource.Token; networkMessageProcessThread = new Thread(PreProcessMessages); networkMessageProcessThread.Start(); + } - _stateDiffCancellationToken = _stateDiffCancellationTokenSource.Token; - stateDiffProcessThread = new Thread(ExecuteStateDiff); - stateDiffProcessThread.Start(); + struct UnprocessedMessage + { + public byte[] bytes; + public DateTime timestamp; } - struct PreProcessedMessage + struct ProcessedMessage { public Message message; public List dbOps; - public Dictionary> inserts; + public DateTime timestamp; + } + + struct PreProcessedMessage + { + public ProcessedMessage processed; + public Dictionary>? subscriptionInserts; } - private readonly BlockingCollection _messageQueue = - new BlockingCollection(new ConcurrentQueue()); + private readonly BlockingCollection _messageQueue = + new(new ConcurrentQueue()); private readonly BlockingCollection _preProcessedNetworkMessages = - new BlockingCollection(new ConcurrentQueue()); + new(new ConcurrentQueue()); - private CancellationTokenSource _preProcessCancellationTokenSource = new CancellationTokenSource(); - private CancellationToken _preProcessCancellationToken; + private readonly CancellationTokenSource _preProcessCancellationTokenSource = new(); + private CancellationToken _preProcessCancellationToken => _preProcessCancellationTokenSource.Token; void PreProcessMessages() { @@ -232,8 +150,8 @@ void PreProcessMessages() { try { - var bytes = _messageQueue.Take(_preProcessCancellationToken); - var preprocessedMessage = PreProcessMessage(bytes); + var message = _messageQueue.Take(_preProcessCancellationToken); + var preprocessedMessage = PreProcessMessage(message); _preProcessedNetworkMessages.Add(preprocessedMessage, _preProcessCancellationToken); } catch (OperationCanceledException) @@ -243,17 +161,15 @@ void PreProcessMessages() } } - PreProcessedMessage PreProcessMessage(byte[] bytes) + PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) { var dbOps = new List(); - using var compressedStream = new MemoryStream(bytes); + using var compressedStream = new MemoryStream(unprocessed.bytes); using var decompressedStream = new BrotliStream(compressedStream, CompressionMode.Decompress); var message = Message.Parser.ParseFrom(decompressedStream); - using var stream = new MemoryStream(); - using var reader = new BinaryReader(stream); // This is all of the inserts - Dictionary> subscriptionInserts = null; + Dictionary>? subscriptionInserts = null; // All row updates that have a primary key, this contains inserts, deletes and updates var primaryKeyChanges = new Dictionary<(System.Type tableType, object primaryKeyValue), DbOp>(); @@ -261,18 +177,16 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) { if (!subscriptionInserts.TryGetValue(tableType, out var hashSet)) { - hashSet = new HashSet(capacity: tableSize, comparer: new ByteArrayComparer()); + hashSet = new HashSet(capacity: tableSize, comparer: ByteArrayComparer.Instance); subscriptionInserts[tableType] = hashSet; } return hashSet; } - SubscriptionUpdate subscriptionUpdate = null; - switch (message.TypeCase) + switch (message) { - case ClientApi.Message.TypeOneofCase.SubscriptionUpdate: - subscriptionUpdate = message.SubscriptionUpdate; + case { TypeCase: Message.TypeOneofCase.SubscriptionUpdate, SubscriptionUpdate: var subscriptionUpdate }: subscriptionInserts = new(capacity: subscriptionUpdate.TableUpdates.Sum(a => a.TableRowOperations.Count)); // First apply all of the state foreach (var update in subscriptionUpdate.TableUpdates) @@ -303,17 +217,8 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) continue; } - stream.Position = 0; - stream.Write(rowBytes, 0, rowBytes.Length); - stream.Position = 0; - stream.SetLength(rowBytes.Length); - var deserializedRow = AlgebraicValue.Deserialize(table.RowSchema, reader); - if (deserializedRow == null) - { - throw new Exception("Failed to deserialize row"); - } - table.SetAndForgetDecodedValue(deserializedRow, out var obj); + var obj = table.DecodeValue(row.Row); var op = new DbOp { table = table, @@ -326,10 +231,9 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) break; - case ClientApi.Message.TypeOneofCase.TransactionUpdate: - subscriptionUpdate = message.TransactionUpdate.SubscriptionUpdate; + case { TypeCase: Message.TypeOneofCase.TransactionUpdate, TransactionUpdate: var transactionUpdate }: // First apply all of the state - foreach (var update in subscriptionUpdate.TableUpdates) + foreach (var update in transactionUpdate.SubscriptionUpdate.TableUpdates) { var tableName = update.TableName; var table = clientDB.GetTable(tableName); @@ -342,18 +246,8 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) foreach (var row in update.TableRowOperations) { var rowBytes = row.Row.ToByteArray(); - stream.Position = 0; - stream.Write(rowBytes, 0, rowBytes.Length); - stream.Position = 0; - stream.SetLength(rowBytes.Length); - var deserializedRow = AlgebraicValue.Deserialize(table.RowSchema, reader); - if (deserializedRow == null) - { - throw new Exception("Failed to deserialize row"); - } - table.SetAndForgetDecodedValue(deserializedRow, out var obj); - var primaryKeyValue = table.GetPrimaryKeyValue(obj); + var obj = table.DecodeValue(row.Row); var op = new DbOp { table = table }; @@ -368,18 +262,17 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) op.delete = dbValue; } - if (primaryKeyValue != null) + if (obj is IDatabaseTableWithPrimaryKey objWithPk) { // Compound key that we use for lookup. // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, primaryKeyValue); + var key = (table.ClientTableType, objWithPk.GetPrimaryKeyValue()); if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { - Logger.LogWarning($"Update with the same primary key was " + - $"applied multiple times! tableName={tableName}"); + Logger.LogWarning($"Update with the same primary key was applied multiple times! tableName={tableName}"); // TODO(jdetter): Is this a correctable error? This would be a major error on the // SpacetimeDB side. continue; @@ -408,28 +301,24 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) // Convert the generic event arguments in to a domain specific event object, this gets fed back into // the message.TransactionUpdate.Event.FunctionCall.CallInfo field. - if (message.TypeCase == Message.TypeOneofCase.TransactionUpdate && - deserializeEventCache.TryGetValue(message.TransactionUpdate.Event.FunctionCall.Reducer, - out var deserializer)) + var dbEvent = message.TransactionUpdate.Event; + try + { + dbEvent.FunctionCall.CallInfo = ReducerEventFromDbEvent(dbEvent); + } + catch (Exception e) { - deserializer.Invoke(message.TransactionUpdate.Event); + Logger.LogException(e); } break; - case ClientApi.Message.TypeOneofCase.IdentityToken: - break; - case ClientApi.Message.TypeOneofCase.Event: - break; - case ClientApi.Message.TypeOneofCase.OneOffQuery: - break; - case ClientApi.Message.TypeOneofCase.OneOffQueryResponse: + case { TypeCase: Message.TypeOneofCase.OneOffQueryResponse, OneOffQueryResponse: var resp }: /// This case does NOT produce a list of DBOps, because it should not modify the client cache state! - var resp = message.OneOffQueryResponse; var messageId = new Guid(resp.MessageId.Span); if (!waitingOneOffQueries.Remove(messageId, out var resultSource)) { - Logger.LogError("Response to unknown one-off-query: " + messageId); + Logger.LogError($"Response to unknown one-off-query: {messageId}"); break; } @@ -439,69 +328,43 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) // Logger.LogWarning($"Total Updates preprocessed: {totalUpdateCount}"); - return new PreProcessedMessage { message = message, dbOps = dbOps, inserts = subscriptionInserts }; + return new PreProcessedMessage + { + processed = new ProcessedMessage { message = message, dbOps = dbOps, timestamp = unprocessed.timestamp }, + subscriptionInserts = subscriptionInserts, + }; } } - struct ProcessedMessage + ProcessedMessage CalculateStateDiff(PreProcessedMessage preProcessedMessage) { - public Message message; - public List dbOps; - } - - // The message that has been preprocessed and has had its state diff calculated + var processed = preProcessedMessage.processed; - private BlockingCollection _stateDiffMessages = new BlockingCollection(); - private CancellationTokenSource _stateDiffCancellationTokenSource = new CancellationTokenSource(); - private CancellationToken _stateDiffCancellationToken; - - void ExecuteStateDiff() - { - while (!isClosing) + // Perform the state diff, this has to be done on the main thread because we have to touch + // the client cache. + if (preProcessedMessage.subscriptionInserts is { } subscriptionInserts) { - try + foreach (var table in clientDB.GetTables()) { - var message = _preProcessedNetworkMessages.Take(_stateDiffCancellationToken); - var (m, events) = CalculateStateDiff(message); - _stateDiffMessages.Add(new ProcessedMessage { dbOps = events, message = m, }); - } - catch (OperationCanceledException) - { - // Normal shutdown - return; - } - } - - (Message, List) CalculateStateDiff(PreProcessedMessage preProcessedMessage) - { - var message = preProcessedMessage.message; - var dbOps = preProcessedMessage.dbOps; - // Perform the state diff, this has to be done on the main thread because we have to touch - // the client cache. - if (message.TypeCase == Message.TypeOneofCase.SubscriptionUpdate) - { - foreach (var table in clientDB.GetTables()) + if (!subscriptionInserts.TryGetValue(table.ClientTableType, out var hashSet)) { - if (!preProcessedMessage.inserts.TryGetValue(table.ClientTableType, out var hashSet)) - { - continue; - } + continue; + } - foreach (var (rowBytes, oldValue) in table.entries.Where(kv => !hashSet.Contains(kv.Key))) + foreach (var (rowBytes, oldValue) in table.Where(kv => !hashSet.Contains(kv.Key))) + { + processed.dbOps.Add(new DbOp { - dbOps.Add(new DbOp - { - table = table, - // This is a row that we had before, but we do not have it now. - // This must have been a delete. - delete = new(oldValue, rowBytes), - }); - } + table = table, + // This is a row that we had before, but we do not have it now. + // This must have been a delete. + delete = new(oldValue, rowBytes), + }); } } - - return (message, dbOps); } + + return processed; } public void Close() @@ -510,9 +373,6 @@ public void Close() connectionClosed = true; webSocket.Close(); _preProcessCancellationTokenSource.Cancel(); - _stateDiffCancellationTokenSource.Cancel(); - - webSocket = null; } /// @@ -520,7 +380,7 @@ public void Close() /// /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - public void Connect(string token, string uri, string addressOrName) + public void Connect(string? token, string uri, string addressOrName) { isClosing = false; @@ -551,18 +411,17 @@ public void Connect(string token, string uri, string addressOrName) }); } - private void OnMessageProcessCompleteUpdate(Message message, List dbOps) - { - var transactionEvent = message.TransactionUpdate?.Event!; + private void OnMessageProcessCompleteUpdate(Event? transactionEvent, List dbOps) + { // First trigger OnBeforeDelete foreach (var update in dbOps) { - if (update.delete is { value: var oldValue }) + if (update is { delete: { value: var oldValue }, insert: null }) { try { - update.table.BeforeDeleteCallback?.Invoke(oldValue, transactionEvent); + oldValue.OnBeforeDeleteEvent(transactionEvent); } catch (Exception e) { @@ -581,7 +440,7 @@ private void OnMessageProcessCompleteUpdate(Message message, List dbOps) { if (update.table.DeleteEntry(delete.bytes)) { - update.table.InternalValueDeletedCallback(delete.value); + delete.value.InternalOnValueDeleted(); } else { @@ -594,7 +453,7 @@ private void OnMessageProcessCompleteUpdate(Message message, List dbOps) { if (update.table.InsertEntry(insert.bytes, insert.value)) { - update.table.InternalValueInsertedCallback(insert.value); + insert.value.InternalOnValueInserted(); } else { @@ -612,15 +471,20 @@ private void OnMessageProcessCompleteUpdate(Message message, List dbOps) switch (dbOp) { case { insert: { value: var newValue }, delete: { value: var oldValue } }: - dbOp.table.UpdateCallback?.Invoke(oldValue, newValue, transactionEvent); - break; + { + // If we matched an update, these values must have primary keys. + var newValue_ = (IDatabaseTableWithPrimaryKey)newValue; + var oldValue_ = (IDatabaseTableWithPrimaryKey)oldValue; + oldValue_.OnUpdateEvent(newValue_, transactionEvent); + break; + } case { insert: { value: var newValue } }: - dbOp.table.InsertCallback?.Invoke(newValue, transactionEvent); + newValue.OnInsertEvent(transactionEvent); break; case { delete: { value: var oldValue } }: - dbOp.table.DeleteCallback?.Invoke(oldValue, transactionEvent); + oldValue.OnDeleteEvent(transactionEvent); break; } } @@ -631,13 +495,20 @@ private void OnMessageProcessCompleteUpdate(Message message, List dbOps) } } - private void OnMessageProcessComplete(Message message, List dbOps) + private void OnMessageProcessComplete(PreProcessedMessage preProcessed) { - switch (message.TypeCase) + var processed = CalculateStateDiff(preProcessed); + var message = processed.message; + var dbOps = processed.dbOps; + var timestamp = processed.timestamp; + + switch (message) { - case Message.TypeOneofCase.SubscriptionUpdate: + case { TypeCase: Message.TypeOneofCase.SubscriptionUpdate, SubscriptionUpdate: var subscriptionUpdate }: onBeforeSubscriptionApplied?.Invoke(); - OnMessageProcessCompleteUpdate(message, dbOps); + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={message.TypeCase}"); + stats.SubscriptionRequestTracker.FinishTrackingRequest(subscriptionUpdate.RequestId); + OnMessageProcessCompleteUpdate(null, dbOps); try { onSubscriptionApplied?.Invoke(); @@ -647,63 +518,76 @@ private void OnMessageProcessComplete(Message message, List dbOps) Logger.LogException(e); } break; - case Message.TypeOneofCase.TransactionUpdate: - OnMessageProcessCompleteUpdate(message, dbOps); + case { TypeCase: Message.TypeOneofCase.TransactionUpdate, TransactionUpdate: var transactionUpdate }: + var transactionEvent = transactionUpdate.Event; + var reducer = transactionEvent.FunctionCall.Reducer; + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={message.TypeCase},reducer={reducer}"); + var hostDuration = TimeSpan.FromMilliseconds(transactionEvent.HostExecutionDurationMicros / 1000.0d); + stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); + var callerIdentity = Identity.From(transactionEvent.CallerIdentity.ToByteArray()); + if (callerIdentity == clientIdentity) + { + // This was a request that we initiated + var requestId = transactionUpdate.SubscriptionUpdate.RequestId; + if (!stats.ReducerRequestTracker.FinishTrackingRequest(requestId)) + { + Logger.LogWarning($"Failed to finish tracking reducer request: {requestId}"); + } + } + OnMessageProcessCompleteUpdate(transactionEvent, dbOps); try { - onEvent?.Invoke(message.TransactionUpdate.Event); + onEvent?.Invoke(transactionEvent); } catch (Exception e) { Logger.LogException(e); } - bool reducerFound = false; - var functionName = message.TransactionUpdate.Event.FunctionCall.Reducer; - if (reducerEventCache.TryGetValue(functionName, out var value)) + if (transactionEvent.FunctionCall.CallInfo is not {} reducerEvent) { - try - { - reducerFound = value.Invoke(message.TransactionUpdate.Event); - } - catch (Exception e) - { - Logger.LogException(e); - } + // If we are here, an error about unknown reducer should have already been logged, so nothing to do. + break; } - if (!reducerFound && message.TransactionUpdate.Event.Status == - ClientApi.Event.Types.Status.Failed) + var reducerFound = false; + try + { + reducerFound = reducerEvent.InvokeHandler(); + } + catch (Exception e) + { + Logger.LogException(e); + } + + if (!reducerFound && transactionEvent.Status == Event.Types.Status.Failed) { try { - onUnhandledReducerError?.Invoke(message.TransactionUpdate.Event.FunctionCall - .CallInfo); + onUnhandledReducerError?.Invoke((ReducerEvent)reducerEvent); } catch (Exception e) { Logger.LogException(e); } } - break; - case Message.TypeOneofCase.IdentityToken: + case { TypeCase: Message.TypeOneofCase.IdentityToken, IdentityToken: var identityToken }: try { - onIdentityReceived?.Invoke(message.IdentityToken.Token, - Identity.From(message.IdentityToken.Identity.ToByteArray()), - (Address)Address.From(message.IdentityToken.Address.ToByteArray())); + clientIdentity = Identity.From(identityToken.Identity.ToByteArray()); + var address = Address.From(identityToken.Address.ToByteArray()) ?? throw new Exception("Received zero address"); + onIdentityReceived?.Invoke(identityToken.Token, clientIdentity, address); } catch (Exception e) { Logger.LogException(e); } - break; - case Message.TypeOneofCase.Event: + case { TypeCase: Message.TypeOneofCase.Event, Event: var event_ }: try { - onEvent?.Invoke(message.Event); + onEvent?.Invoke(event_); } catch (Exception e) { @@ -714,9 +598,11 @@ private void OnMessageProcessComplete(Message message, List dbOps) } } - private void OnMessageReceived(byte[] bytes) => _messageQueue.Add(bytes); + private void OnMessageReceived(byte[] bytes, DateTime timestamp) => + _messageQueue.Add(new UnprocessedMessage { bytes = bytes, timestamp = timestamp }); - public void InternalCallReducer(string json) + public void InternalCallReducer(T args) + where T : IReducerArgsBase, new() { if (!webSocket.IsConnected) { @@ -724,7 +610,15 @@ public void InternalCallReducer(string json) return; } - webSocket.Send(Encoding.ASCII.GetBytes("{ \"call\": " + json + " }")); + webSocket.Send(new Message + { + FunctionCall = new FunctionCall + { + RequestId = stats.ReducerRequestTracker.StartTrackingRequest(args.ReducerName), + Reducer = args.ReducerName, + ArgBytes = args.ToProtoBytes(), + }, + }); } public void Subscribe(List queries) @@ -735,13 +629,17 @@ public void Subscribe(List queries) return; } - var json = JsonConvert.SerializeObject(queries); - // should we use UTF8 here? ASCII is fragile. - webSocket.Send(Encoding.ASCII.GetBytes("{ \"subscribe\": { \"query_strings\": " + json + " }}")); + var request = new ClientApi.Subscribe + { + RequestId = stats.SubscriptionRequestTracker.StartTrackingRequest(), + }; + request.QueryStrings.AddRange(queries); + webSocket.Send(new Message { Subscribe = request }); } - /// Usage: SpacetimeDBClient.instance.OneOffQuery("WHERE sender = \"bob\""); - public async Task OneOffQuery(string query) where T : IDatabaseTable + /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("WHERE sender = \"bob\""); + public async Task OneOffQuery(string query) + where T : IDatabaseTable, IStructuralReadWrite, new() { var messageId = Guid.NewGuid(); var type = typeof(T); @@ -750,20 +648,29 @@ public async Task OneOffQuery(string query) where T : IDatabaseTable // unsanitized here, but writes will be prevented serverside. // the best they can do is send multiple selects, which will just result in them getting no data back. - string queryString = "SELECT * FROM " + type.Name + " " + query; + string queryString = $"SELECT * FROM {type.Name} {query}"; - // see: SpacetimeDB\crates\core\src\client\message_handlers.rs, enum Message<'a> - var serializedQuery = "{ \"one_off_query\": { \"message_id\": \"" + - System.Convert.ToBase64String(messageId.ToByteArray()) + - "\", \"query_string\": " + JsonConvert.SerializeObject(queryString) + " } }"; - webSocket.Send(Encoding.UTF8.GetBytes(serializedQuery)); + var requestId = stats.OneOffRequestTracker.StartTrackingRequest(); + webSocket.Send(new Message + { + OneOffQuery = new ClientApi.OneOffQuery + { + MessageId = UnsafeByteOperations.UnsafeWrap(messageId.ToByteArray()), + QueryString = queryString, + } + }); // Suspend for an arbitrary amount of time var result = await resultSource.Task; + if (!stats.OneOffRequestTracker.FinishTrackingRequest(requestId)) + { + Logger.LogWarning($"Failed to finish tracking one off request: {requestId}"); + } + T[] LogAndThrow(string error) { - error = "While processing one-off-query `" + queryString + "`, ID " + messageId + ": " + error; + error = $"While processing one-off-query `{queryString}`, ID {messageId}: {error}"; Logger.LogError(error); throw new Exception(error); } @@ -771,49 +678,33 @@ T[] LogAndThrow(string error) // The server got back to us if (result.Error != null && result.Error != "") { - return LogAndThrow("Server error: " + result.Error); + return LogAndThrow($"Server error: {result.Error}"); } if (result.Tables.Count != 1) { - return LogAndThrow("Expected a single table, but got " + result.Tables.Count); + return LogAndThrow($"Expected a single table, but got {result.Tables.Count}"); } var resultTable = result.Tables[0]; var cacheTable = clientDB.GetTable(resultTable.TableName); - if (cacheTable.ClientTableType != type) - { - return LogAndThrow("Mismatched result type, expected " + type + " but got " + resultTable.TableName); - } - - T[] results = (T[])Array.CreateInstance(type, resultTable.Row.Count); - using var stream = new MemoryStream(); - using var reader = new BinaryReader(stream); - for (int i = 0; i < results.Length; i++) + if (cacheTable?.ClientTableType != type) { - var rowValue = resultTable.Row[i].ToByteArray(); - stream.Position = 0; - stream.Write(rowValue, 0, rowValue.Length); - stream.Position = 0; - stream.SetLength(rowValue.Length); - - var deserialized = AlgebraicValue.Deserialize(cacheTable.RowSchema, reader); - cacheTable.SetAndForgetDecodedValue(deserialized, out var obj); - results[i] = (T)obj; + return LogAndThrow($"Mismatched result type, expected {type} but got {resultTable.TableName}"); } - return results; + return resultTable.Row.Select(row => BSATNHelpers.FromProtoBytes(row)).ToArray(); } - public bool IsConnected() => webSocket != null && webSocket.IsConnected; + public bool IsConnected() => webSocket.IsConnected; public void Update() { webSocket.Update(); - while (_stateDiffMessages.TryTake(out var stateDiffMessage)) + while (_preProcessedNetworkMessages.TryTake(out var preProcessedMessage)) { - OnMessageProcessComplete(stateDiffMessage.message, stateDiffMessage.dbOps); + OnMessageProcessComplete(preProcessedMessage); } } } diff --git a/sdks/csharp/src/Stats.cs b/sdks/csharp/src/Stats.cs new file mode 100644 index 00000000000..0d0ff3fcc51 --- /dev/null +++ b/sdks/csharp/src/Stats.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; + +namespace SpacetimeDB +{ + public class NetworkRequestTracker + { + private readonly ConcurrentQueue<(DateTime End, TimeSpan Duration, string Metadata)> _requestDurations = new(); + + private uint _nextRequestId; + private readonly Dictionary _requests = new(); + + public uint StartTrackingRequest(string metadata = "") + { + // Record the start time of the request + var newRequestId = ++_nextRequestId; + _requests[newRequestId] = (DateTime.UtcNow, metadata); + return newRequestId; + } + + public bool FinishTrackingRequest(uint requestId) + { + if (!_requests.Remove(requestId, out var entry)) + { + // TODO: When we implement requestId json support for SpacetimeDB this shouldn't happen anymore! + // var minKey = _requests.Keys.Min(); + // entry = _requests[minKey]; + // + // if (!_requests.Remove(minKey)) + // { + // return false; + // } + return false; + } + + // Calculate the duration and add it to the queue + InsertRequest(entry.Start, entry.Metadata); + return true; + } + + public void InsertRequest(TimeSpan duration, string metadata) + { + _requestDurations.Enqueue((DateTime.UtcNow, duration, metadata)); + } + + public void InsertRequest(DateTime start, string metadata) + { + InsertRequest(DateTime.UtcNow - start, metadata); + } + + public ((TimeSpan Duration, string Metadata) Min, (TimeSpan Duration, string Metadata) Max)? GetMinMaxTimes(int lastSeconds) + { + var cutoff = DateTime.UtcNow.AddSeconds(-lastSeconds); + var requestDurations = _requestDurations.Where(x => x.End >= cutoff).Select(x => (x.Duration, x.Metadata)); + + if (!requestDurations.Any()) + { + return null; + } + + return (requestDurations.Min(), requestDurations.Max()); + } + + public int GetSampleCount() => _requestDurations.Count; + public int GetRequestsAwaitingResponse() => _requests.Count; + } + + public class Stats + { + public NetworkRequestTracker ReducerRequestTracker = new(); + public NetworkRequestTracker OneOffRequestTracker = new(); + public NetworkRequestTracker SubscriptionRequestTracker = new(); + public NetworkRequestTracker AllReducersTracker = new(); + public NetworkRequestTracker ParseMessageTracker = new(); + } +} diff --git a/sdks/csharp/src/Stubs.cs b/sdks/csharp/src/Stubs.cs index 36f1ef1b9d7..9e43197a230 100644 --- a/sdks/csharp/src/Stubs.cs +++ b/sdks/csharp/src/Stubs.cs @@ -1,27 +1,32 @@ -using System.Collections; -using System.Collections.Generic; - -namespace SpacetimeDB -{ - public partial class ReducerEventBase +namespace SpacetimeDB +{ + public interface IReducerArgsBase : BSATN.IStructuralReadWrite { - public string ReducerName { get; private set; } - public ulong Timestamp { get; private set; } - public SpacetimeDB.Identity Identity { get; private set; } - public SpacetimeDB.Address? CallerAddress { get; private set; } - public string ErrMessage { get; private set; } - public ClientApi.Event.Types.Status Status { get; private set; } - protected object Args; + string ReducerName { get; } + } - public ReducerEventBase(string reducerName, ulong timestamp, SpacetimeDB.Identity identity, SpacetimeDB.Address? callerAddress, string errMessage, ClientApi.Event.Types.Status status, object args) + public abstract class ReducerEventBase + { + public ulong Timestamp { get; } + public SpacetimeDB.Identity? Identity { get; } + public SpacetimeDB.Address? CallerAddress { get; } + public string? ErrMessage { get; } + public ClientApi.Event.Types.Status Status { get; } + + public ReducerEventBase() { - ReducerName = reducerName; - Timestamp = timestamp; - Identity = identity; - CallerAddress = callerAddress; - ErrMessage = errMessage; - Status = status; - Args = args; - } - } -} + Status = ClientApi.Event.Types.Status.Committed; + } + + public ReducerEventBase(ClientApi.Event dbEvent) + { + Timestamp = dbEvent.Timestamp; + Identity = SpacetimeDB.Identity.From(dbEvent.CallerIdentity.ToByteArray()); + CallerAddress = Address.From(dbEvent.CallerAddress.ToByteArray()); + ErrMessage = dbEvent.Message; + Status = dbEvent.Status; + } + + public abstract bool InvokeHandler(); + } +} diff --git a/sdks/csharp/src/Utils.cs b/sdks/csharp/src/Utils.cs index 57b4f856dbb..52f6f8a21cf 100644 --- a/sdks/csharp/src/Utils.cs +++ b/sdks/csharp/src/Utils.cs @@ -2,6 +2,13 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; +#if UNITY_5_3_OR_NEWER +namespace System.Runtime.CompilerServices +{ + public static class IsExternalInit {} +} +#endif + namespace SpacetimeDB { // Note: this utility struct is used by an autogenerated C# code so it needs to be public. diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 4dcd8a34b08..8422b14605b 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -5,16 +5,17 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Google.Protobuf; namespace SpacetimeDB { public delegate void WebSocketOpenEventHandler(); - public delegate void WebSocketMessageEventHandler(byte[] message); + public delegate void WebSocketMessageEventHandler(byte[] message, DateTime timestamp); public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); - public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error, string? message); + public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error, string message); public delegate void WebSocketSendErrorEventHandler(Exception e); public struct ConnectOptions @@ -48,7 +49,7 @@ public WebSocket(ConnectOptions options) public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } - public async Task Connect(string auth, string host, string nameOrAddress, Address clientAddress) + public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress) { var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}"); Ws.Options.AddSubProtocol(_options.Protocol); @@ -58,7 +59,7 @@ public async Task Connect(string auth, string host, string nameOrAddress, Addres { var tokenBytes = Encoding.UTF8.GetBytes($"token:{auth}"); var base64 = Convert.ToBase64String(tokenBytes); - Ws.Options.SetRequestHeader("Authorization", "Basic " + base64); + Ws.Options.SetRequestHeader("Authorization", $"Basic {base64}"); } else { @@ -104,6 +105,7 @@ await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, return; } + var startReceive = DateTime.UtcNow; var count = receiveResult.Count; while (receiveResult.EndOfMessage == false) { @@ -126,7 +128,7 @@ await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, if (OnMessage != null) { var message = _receiveBuffer.Take(count).ToArray(); - dispatchQueue.Enqueue(() => OnMessage(message)); + dispatchQueue.Enqueue(() => OnMessage(message, startReceive)); } } catch (WebSocketException ex) @@ -153,11 +155,11 @@ public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure /// before we start another one. This function is also thread safe, just in case. /// /// The message to send - public void Send(byte[] message) + public void Send(ClientApi.Message message) { lock (messageSendQueue) { - messageSendQueue.Enqueue(message); + messageSendQueue.Enqueue(message.ToByteArray()); senderTask ??= Task.Run(ProcessSendQueue); } } @@ -181,7 +183,7 @@ private async Task ProcessSendQueue() } } - await Ws!.SendAsync(message, WebSocketMessageType.Text, true, CancellationToken.None); + await Ws!.SendAsync(message, WebSocketMessageType.Binary, true, CancellationToken.None); } } catch (Exception e) diff --git a/sdks/csharp/src/json/EnumAttribute.cs b/sdks/csharp/src/json/EnumAttribute.cs deleted file mode 100644 index 3a66e895c2a..00000000000 --- a/sdks/csharp/src/json/EnumAttribute.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace SpacetimeDB -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] - public class EnumAttribute : Attribute - { - } -} diff --git a/sdks/csharp/src/json/EnumWrapper.cs b/sdks/csharp/src/json/EnumWrapper.cs deleted file mode 100644 index 6ee6fd054b6..00000000000 --- a/sdks/csharp/src/json/EnumWrapper.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections; -using System.Collections.Generic; - -namespace SpacetimeDB -{ - public class EnumWrapper - { - public T Value { get; set; } - - public EnumWrapper(T value) - { - Value = value; - } - } -} diff --git a/sdks/csharp/src/json/EnumWrapperConverter.cs b/sdks/csharp/src/json/EnumWrapperConverter.cs deleted file mode 100644 index 1074c7f5d4f..00000000000 --- a/sdks/csharp/src/json/EnumWrapperConverter.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using Namespace; -using Newtonsoft.Json; - -namespace SpacetimeDB -{ - public class EnumWrapperConverter : JsonConverter - { - public override bool CanConvert(Type objectType) => objectType == typeof(EnumWrapper<>); - - public override object ReadJson( - JsonReader reader, - Type objectType, - object existingValue, - JsonSerializer serializer - ) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteStartObject(); - writer.WritePropertyName(value.ToString()); - writer.WriteRawValue("{}"); - writer.WriteEndObject(); - - } - } -} diff --git a/sdks/csharp/src/json/JsonContractResolver.cs b/sdks/csharp/src/json/JsonContractResolver.cs deleted file mode 100644 index 1b6532f9fa6..00000000000 --- a/sdks/csharp/src/json/JsonContractResolver.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; - -namespace SpacetimeDB -{ - public class SomeConverter : JsonConverter - { - public override bool CanConvert(Type objectType) => true; - - public override object ReadJson( - JsonReader reader, - Type objectType, - object existingValue, - JsonSerializer serializer - ) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteStartObject(); - writer.WritePropertyName("some"); - serializer.Serialize(writer, value); - writer.WriteEndObject(); - } - } - - public class EnumConverter : JsonConverter - { - public override bool CanConvert(Type objectType) => true; - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, - JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteStartObject(); - writer.WritePropertyName(value.ToString()); - writer.WriteRawValue("{}"); - writer.WriteEndObject(); - } - } - - public class JsonContractResolver : DefaultContractResolver - { - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - var property = base.CreateProperty(member, memberSerialization); - - if (member.GetCustomAttribute() != null) - { - property.Converter = new SomeConverter(); - } else if (member.GetCustomAttribute() != null) - { - - property.Converter = new EnumConverter(); - } - - return property; - } - } -} diff --git a/sdks/csharp/src/json/SomeAttribute.cs b/sdks/csharp/src/json/SomeAttribute.cs deleted file mode 100644 index 77bbc91869e..00000000000 --- a/sdks/csharp/src/json/SomeAttribute.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace SpacetimeDB -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] - public class SomeAttribute : Attribute - { - } -} diff --git a/sdks/csharp/src/json/SomeWrapper.cs b/sdks/csharp/src/json/SomeWrapper.cs deleted file mode 100644 index a7589344f3c..00000000000 --- a/sdks/csharp/src/json/SomeWrapper.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections; -using System.Collections.Generic; - -namespace Namespace -{ - public class SomeWrapper - { - public T Value { get; set; } - - public SomeWrapper(T value) - { - Value = value; - } - } -} diff --git a/sdks/csharp/src/json/SomeWrapperConverter.cs b/sdks/csharp/src/json/SomeWrapperConverter.cs deleted file mode 100644 index b5f2640007f..00000000000 --- a/sdks/csharp/src/json/SomeWrapperConverter.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using Namespace; -using Newtonsoft.Json; - -namespace SpacetimeDB -{ - public class SomeWrapperConverter : JsonConverter - { - public override bool CanConvert(Type objectType) => objectType == typeof(SomeWrapper<>); - - public override object ReadJson( - JsonReader reader, - Type objectType, - object existingValue, - JsonSerializer serializer - ) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteStartObject(); - writer.WritePropertyName("some"); - serializer.Serialize(writer, value); - writer.WriteEndObject(); - } - } -} \ No newline at end of file From 53d6f9c3edf5f40acd06683cc7eea3e0378b3756 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 13 Jun 2024 14:51:31 -0700 Subject: [PATCH 084/223] Release v0.10.0 (#98) ## Description of Changes Changes for release 0.10. --------- Co-authored-by: Zeke Foppa Co-authored-by: Ingvar Stepanyan --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 6 +++--- sdks/csharp/examples/quickstart/client/client.csproj | 2 +- sdks/csharp/examples/quickstart/client/client.sln | 12 ------------ 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 2e976e56139..f1360e3ff3e 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -17,8 +17,8 @@ logo.png README.md https://github.com/clockworklabs/spacetimedb-csharp-sdk - 0.8.0 - 0.9.2 + 0.10.0 + $(AssemblyVersion) @@ -29,7 +29,7 @@ - + diff --git a/sdks/csharp/examples/quickstart/client/client.csproj b/sdks/csharp/examples/quickstart/client/client.csproj index edbe73206c3..ad685fa7c1f 100644 --- a/sdks/csharp/examples/quickstart/client/client.csproj +++ b/sdks/csharp/examples/quickstart/client/client.csproj @@ -9,7 +9,7 @@ - + diff --git a/sdks/csharp/examples/quickstart/client/client.sln b/sdks/csharp/examples/quickstart/client/client.sln index f14225a238c..524c0df2b82 100644 --- a/sdks/csharp/examples/quickstart/client/client.sln +++ b/sdks/csharp/examples/quickstart/client/client.sln @@ -7,10 +7,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "client.csproj", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpacetimeDB.ClientSDK", "..\..\..\SpacetimeDB.ClientSDK.csproj", "{242A8146-A58D-43E9-A2BD-31FFC6851AA6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Codegen", "..\..\..\..\SpacetimeDB\crates\bindings-csharp\BSATN.Codegen\BSATN.Codegen.csproj", "{C7C0ED26-79E4-478B-8B15-71E2B078541D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Runtime", "..\..\..\..\SpacetimeDB\crates\bindings-csharp\BSATN.Runtime\BSATN.Runtime.csproj", "{BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -25,14 +21,6 @@ Global {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.Build.0 = Release|Any CPU - {C7C0ED26-79E4-478B-8B15-71E2B078541D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C7C0ED26-79E4-478B-8B15-71E2B078541D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C7C0ED26-79E4-478B-8B15-71E2B078541D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C7C0ED26-79E4-478B-8B15-71E2B078541D}.Release|Any CPU.Build.0 = Release|Any CPU - {BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BD1F3C9B-CEA0-4447-B754-4BF55D6C509F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From b648b9ca88a51213e52e7e6b7601e4e67de073a7 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 15 Jun 2024 16:45:43 +0100 Subject: [PATCH 085/223] Autoformat & verify on CI --- sdks/csharp/.github/workflows/dotnet.yml | 5 ++++- sdks/csharp/src/AuthToken.cs | 4 ++-- sdks/csharp/src/BSATNHelpers.cs | 2 +- sdks/csharp/src/ClientCache.cs | 6 +++--- sdks/csharp/src/SpacetimeDBClient.cs | 6 +++--- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml index 74bfc91e80e..c2658a614af 100644 --- a/sdks/csharp/.github/workflows/dotnet.yml +++ b/sdks/csharp/.github/workflows/dotnet.yml @@ -17,5 +17,8 @@ jobs: with: dotnet-version: 7.0.x - name: Build client example - run: dotnet build + run: dotnet build -warnaserror + working-directory: examples/quickstart/client + - name: Verify formatting + run: dotnet format --check client.sln working-directory: examples/quickstart/client diff --git a/sdks/csharp/src/AuthToken.cs b/sdks/csharp/src/AuthToken.cs index 0b9dcddd87f..2fce2f73d34 100644 --- a/sdks/csharp/src/AuthToken.cs +++ b/sdks/csharp/src/AuthToken.cs @@ -117,10 +117,10 @@ public static void SaveToken(string token) public static string GetTokenKey() { var key = "spacetimedb.identity_token"; - #if UNITY_EDITOR +#if UNITY_EDITOR // Different editors need different keys key += $" - {Application.dataPath}"; - #endif +#endif return key; } } diff --git a/sdks/csharp/src/BSATNHelpers.cs b/sdks/csharp/src/BSATNHelpers.cs index ebb7afdd3d6..3ea5f79aac5 100644 --- a/sdks/csharp/src/BSATNHelpers.cs +++ b/sdks/csharp/src/BSATNHelpers.cs @@ -45,7 +45,7 @@ public override int Read(byte[] buffer, int offset, int count) // Our stream is read-only. public override bool CanWrite => false; public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); - public override void Flush() {} + public override void Flush() { } public override void SetLength(long value) => throw new NotSupportedException(); } diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index f4f67d36484..c4a664e74bc 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -18,11 +18,11 @@ public interface ITableCache : IEnumerable> } public class TableCache : ITableCache - where T: IDatabaseTable, IStructuralReadWrite, new() + where T : IDatabaseTable, IStructuralReadWrite, new() { public Type ClientTableType => typeof(T); - public static readonly Dictionary Entries = new (ByteArrayComparer.Instance); + public static readonly Dictionary Entries = new(ByteArrayComparer.Instance); /// /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. @@ -59,7 +59,7 @@ public bool DeleteEntry(byte[] rowBytes) private readonly Dictionary tables = new(); public void AddTable() - where T: IDatabaseTable, IStructuralReadWrite, new() + where T : IDatabaseTable, IStructuralReadWrite, new() { string name = typeof(T).Name; diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index ca7f8710cea..642c1592fa4 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -436,7 +436,7 @@ private void OnMessageProcessCompleteUpdate(Event? transactionEvent, List // TODO: Reimplement updates when we add support for primary keys var update = dbOps[i]; - if (update.delete is {} delete) + if (update.delete is { } delete) { if (update.table.DeleteEntry(delete.bytes)) { @@ -449,7 +449,7 @@ private void OnMessageProcessCompleteUpdate(Event? transactionEvent, List } } - if (update.insert is {} insert) + if (update.insert is { } insert) { if (update.table.InsertEntry(insert.bytes, insert.value)) { @@ -544,7 +544,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) Logger.LogException(e); } - if (transactionEvent.FunctionCall.CallInfo is not {} reducerEvent) + if (transactionEvent.FunctionCall.CallInfo is not { } reducerEvent) { // If we are here, an error about unknown reducer should have already been logged, so nothing to do. break; From 0267f0233261cc64833ab34fa54a0fcea96f7be3 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 15 Jun 2024 22:04:50 +0100 Subject: [PATCH 086/223] Add snapshot-based tests --- sdks/csharp/.github/workflows/dotnet.yml | 12 +- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 9 +- .../client.sln => SpacetimeDB.ClientSDK.sln} | 68 ++- .../examples/quickstart/client/client.csproj | 6 +- .../examples/quickstart/server/Cargo.lock | 286 ++------- .../examples/quickstart/server/Cargo.toml | 2 +- sdks/csharp/src/SpacetimeDBClient.cs | 5 +- ...otTests.VerifyAllTablesParsed.verified.txt | 565 ++++++++++++++++++ sdks/csharp/tests/SnapshotTests.cs | 156 +++++ sdks/csharp/tests/VerifyInit.cs | 44 ++ sdks/csharp/tests/tests.csproj | 29 + 11 files changed, 903 insertions(+), 279 deletions(-) rename sdks/csharp/{examples/quickstart/client/client.sln => SpacetimeDB.ClientSDK.sln} (66%) create mode 100644 sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt create mode 100644 sdks/csharp/tests/SnapshotTests.cs create mode 100644 sdks/csharp/tests/VerifyInit.cs create mode 100644 sdks/csharp/tests/tests.csproj diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml index c2658a614af..1b93dfbe229 100644 --- a/sdks/csharp/.github/workflows/dotnet.yml +++ b/sdks/csharp/.github/workflows/dotnet.yml @@ -16,9 +16,11 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: 7.0.x - - name: Build client example - run: dotnet build -warnaserror - working-directory: examples/quickstart/client + - name: Restore dependencies + run: dotnet restore + - name: Build everything + run: dotnet build --no-restore -warnaserror + - name: Run tests + run: dotnet test --no-build - name: Verify formatting - run: dotnet format --check client.sln - working-directory: examples/quickstart/client + run: dotnet format --no-restore --verify-no-changes SpacetimeDB.ClientSDK.sln diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index f1360e3ff3e..a6c750c1f40 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -19,17 +19,14 @@ https://github.com/clockworklabs/spacetimedb-csharp-sdk 0.10.0 $(AssemblyVersion) + $(DefaultItemExcludes);examples/**;tests/** - - - - - - + + diff --git a/sdks/csharp/examples/quickstart/client/client.sln b/sdks/csharp/SpacetimeDB.ClientSDK.sln similarity index 66% rename from sdks/csharp/examples/quickstart/client/client.sln rename to sdks/csharp/SpacetimeDB.ClientSDK.sln index 524c0df2b82..f6836b1ee66 100644 --- a/sdks/csharp/examples/quickstart/client/client.sln +++ b/sdks/csharp/SpacetimeDB.ClientSDK.sln @@ -1,31 +1,37 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.6.33717.318 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "client.csproj", "{8F33709C-DEE9-41CC-A477-D6128E3700B1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpacetimeDB.ClientSDK", "..\..\..\SpacetimeDB.ClientSDK.csproj", "{242A8146-A58D-43E9-A2BD-31FFC6851AA6}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.Build.0 = Release|Any CPU - {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {35C59D87-64E5-4A6C-B1D5-2241B946E847} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33717.318 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples\quickstart\client\client.csproj", "{8F33709C-DEE9-41CC-A477-D6128E3700B1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpacetimeDB.ClientSDK", "SpacetimeDB.ClientSDK.csproj", "{242A8146-A58D-43E9-A2BD-31FFC6851AA6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests\tests.csproj", "{5CD31104-4719-4CE3-8D39-8BAE0B75C085}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.Build.0 = Release|Any CPU + {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.Build.0 = Release|Any CPU + {5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {35C59D87-64E5-4A6C-B1D5-2241B946E847} + EndGlobalSection +EndGlobal diff --git a/sdks/csharp/examples/quickstart/client/client.csproj b/sdks/csharp/examples/quickstart/client/client.csproj index ad685fa7c1f..f5c7cde4fee 100644 --- a/sdks/csharp/examples/quickstart/client/client.csproj +++ b/sdks/csharp/examples/quickstart/client/client.csproj @@ -5,6 +5,8 @@ net7.0 disable enable + + false @@ -12,8 +14,4 @@ - - - - diff --git a/sdks/csharp/examples/quickstart/server/Cargo.lock b/sdks/csharp/examples/quickstart/server/Cargo.lock index 77aa8859440..372fb071956 100644 --- a/sdks/csharp/examples/quickstart/server/Cargo.lock +++ b/sdks/csharp/examples/quickstart/server/Cargo.lock @@ -83,31 +83,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - [[package]] name = "crypto-common" version = "0.1.6" @@ -169,12 +144,6 @@ dependencies = [ "syn 2.0.32", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "generic-array" version = "0.14.7" @@ -185,6 +154,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -193,8 +173,6 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", - "rayon", - "serde", ] [[package]] @@ -233,27 +211,11 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" -version = "0.2.147" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "log" @@ -261,12 +223,6 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" -[[package]] -name = "memchr" -version = "2.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -289,33 +245,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] -name = "parking_lot" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "paste" -version = "1.0.15" +name = "ppv-lite86" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" @@ -326,27 +259,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prometheus" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" -dependencies = [ - "cfg-if", - "fnv", - "lazy_static", - "memchr", - "parking_lot", - "protobuf", - "thiserror", -] - -[[package]] -name = "protobuf" -version = "2.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" - [[package]] name = "quote" version = "1.0.29" @@ -357,32 +269,33 @@ dependencies = [ ] [[package]] -name = "rayon" -version = "1.10.0" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "either", - "rayon-core", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "rayon-core" -version = "1.12.1" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "crossbeam-deque", - "crossbeam-utils", + "ppv-lite86", + "rand_core", ] [[package]] -name = "redox_syscall" -version = "0.5.1" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "bitflags", + "getrandom", ] [[package]] @@ -401,10 +314,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] -name = "scopeguard" -version = "1.2.0" +name = "second-stack" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "4904c83c6e51f1b9b08bfa5a86f35a51798e8307186e6f5513852210a219c0bb" [[package]] name = "semver" @@ -412,26 +325,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -[[package]] -name = "serde" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.32", -] - [[package]] name = "sha3" version = "0.10.8" @@ -459,12 +352,14 @@ dependencies = [ [[package]] name = "spacetimedb" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6521d61527095caf5afde8324c36f8a96555c1a5ab818aec27d933e7abc03cb" +checksum = "4ec3fbc884bd532f1f9cddcde961686284091dfa3facd49b71c553df28d30a5f" dependencies = [ "derive_more", + "getrandom", "log", + "rand", "scoped-tls", "spacetimedb-bindings-macro", "spacetimedb-bindings-sys", @@ -474,9 +369,9 @@ dependencies = [ [[package]] name = "spacetimedb-bindings-macro" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb0093e45b8162365543edfb40d38d3494767fdeb2053f2d8574c7cf2f3d69" +checksum = "6a5a6d8be2a892ae1d1175b228f12deffb685947cc30d60449dba98219cc3bc2" dependencies = [ "bitflags", "humantime", @@ -488,18 +383,18 @@ dependencies = [ [[package]] name = "spacetimedb-bindings-sys" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56d64f5a3121019e81668b1b473a280e0ca4c370c029806d786e4280fb66ce6" +checksum = "a450cdc41a3d6a6a33ba113255c2a1d73dbf32bcf7aa2d272beb58cc6efe9655" dependencies = [ "spacetimedb-primitives", ] [[package]] name = "spacetimedb-data-structures" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35dee07b3444c0458449ceaa1031764e091d87037c73ed163c80b0481c74715" +checksum = "6d866aa0c287936e13f03206f32c15ce46893076918b7d1d9e1a1421ddca2e6a" dependencies = [ "hashbrown", "nohash-hasher", @@ -508,9 +403,9 @@ dependencies = [ [[package]] name = "spacetimedb-lib" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7623594632219c3099e489820a32d0cc683c97ee9a1fe928288ef399960691ff" +checksum = "d0c1d4c3106bdfe395c8f266df1daff9e6259322bd70d05e3f78c7fa67efd14f" dependencies = [ "anyhow", "bitflags", @@ -519,40 +414,27 @@ dependencies = [ "hex", "itertools", "spacetimedb-bindings-macro", - "spacetimedb-metrics", "spacetimedb-primitives", "spacetimedb-sats", "thiserror", ] -[[package]] -name = "spacetimedb-metrics" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d55f007099699a71d5338d44eb8790ba307fcc2771c34565624ba213b9471ab0" -dependencies = [ - "arrayvec", - "itertools", - "paste", - "prometheus", -] - [[package]] name = "spacetimedb-primitives" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8350fd9d7df7234e965c433aaf46b134c00bddf645e80d2e3c7c0e824592959a" +checksum = "38f80f43ce78747ae4deb061130fcbedf9c57cbe9d3db8269e2ce403d6cf3a0c" dependencies = [ "bitflags", "either", - "spacetimedb-data-structures", + "nohash-hasher", ] [[package]] name = "spacetimedb-sats" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e60a059eabb85405a74b9d73751ff58d10fb2229d4b28e97c5519e6b305d2fc" +checksum = "7ab8da7807277abaef5452d25c3cbc01978297a37d0f00071e52621e655b3a84" dependencies = [ "arrayvec", "bitflags", @@ -561,11 +443,11 @@ dependencies = [ "enum-as-inner", "hex", "itertools", + "second-stack", "sha3", "smallvec", "spacetimedb-bindings-macro", "spacetimedb-data-structures", - "spacetimedb-metrics", "spacetimedb-primitives", "thiserror", ] @@ -631,68 +513,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "zerocopy" diff --git a/sdks/csharp/examples/quickstart/server/Cargo.toml b/sdks/csharp/examples/quickstart/server/Cargo.toml index 5bf84e2c7c0..735a5ad6c8c 100644 --- a/sdks/csharp/examples/quickstart/server/Cargo.toml +++ b/sdks/csharp/examples/quickstart/server/Cargo.toml @@ -9,6 +9,6 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -spacetimedb = "0.9" +spacetimedb = "0.10" log = "0.4" anyhow = "1.0" diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 642c1592fa4..d78f1185023 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -141,6 +141,8 @@ struct PreProcessedMessage private readonly BlockingCollection _preProcessedNetworkMessages = new(new ConcurrentQueue()); + internal bool HasPreProcessedMessage => _preProcessedNetworkMessages.Count > 0; + private readonly CancellationTokenSource _preProcessCancellationTokenSource = new(); private CancellationToken _preProcessCancellationToken => _preProcessCancellationTokenSource.Token; @@ -598,7 +600,8 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } } - private void OnMessageReceived(byte[] bytes, DateTime timestamp) => + // Note: this method is called from unit tests. + internal void OnMessageReceived(byte[] bytes, DateTime timestamp) => _messageQueue.Add(new UnprocessedMessage { bytes = bytes, timestamp = timestamp }); public void InternalCallReducer(T args) diff --git a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt new file mode 100644 index 00000000000..66e66a98620 --- /dev/null +++ b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -0,0 +1,565 @@ +{ + Events: { + OnIdentityReceived: { + identity: (identity of A), + address: Guid_1 + }, + OnInsertUser: { + user: { + identity: (identity of A), + online: true + } + }, + OnUpdateUser: { + oldUser: { + identity: (identity of A), + online: true + }, + newUser: { + identity: (identity of A), + name: A, + online: true + }, + reducerEvent: { + Args: { + Name: A + }, + Timestamp: 1718468803659084, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718468803659084, + CallerIdentity: (identity of A), + FunctionCall: { + Reducer: set_name, + ArgBytes: 0100000041, + RequestId: 1, + CallInfo: { + Args: { + Name: A + }, + Timestamp: 1718468803659084, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 4345615, + HostExecutionDurationMicros: 146, + CallerAddress: Guid_1 + }, + OnSetName: { + Args: { + Name: A + }, + Timestamp: 1718468803659084, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + }, + OnInsertMessage: { + message: { + sender: (identity of A), + sent: 1718468812745975, + text: Hello, world! + }, + reducerEvent: { + Args: { + Text: Hello, world! + }, + Timestamp: 1718468812745975, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718468812745975, + CallerIdentity: (identity of A), + FunctionCall: { + Reducer: send_message, + ArgBytes: 0D00000048656C6C6F2C20776F726C6421, + RequestId: 2, + CallInfo: { + Args: { + Text: Hello, world! + }, + Timestamp: 1718468812745975, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2955615, + HostExecutionDurationMicros: 42, + CallerAddress: Guid_1 + }, + OnSendMessage: { + Args: { + Text: Hello, world! + }, + Timestamp: 1718468812745975, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + }, + LogException: Unknown reducer __identity_connected__ (Parameter 'Reducer'), + OnInsertUser: { + user: { + identity: (identity of B), + online: true + } + }, + OnEvent: { + Timestamp: 1718468879237990, + CallerIdentity: (identity of B), + FunctionCall: { + Reducer: __identity_connected__, + ArgBytes: + }, + Message: , + EnergyQuantaUsed: 1957615, + HostExecutionDurationMicros: 70, + CallerAddress: Guid_2 + }, + OnIdentityReceived: { + identity: (identity of B), + address: Guid_2 + }, + OnUpdateUser: { + oldUser: { + identity: (identity of B), + online: true + }, + newUser: { + identity: (identity of B), + name: B, + online: true + }, + reducerEvent: { + Args: { + Name: B + }, + Timestamp: 1718468882638019, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718468882638019, + CallerIdentity: (identity of B), + FunctionCall: { + Reducer: set_name, + ArgBytes: 0100000042, + RequestId: 1, + CallInfo: { + Args: { + Name: B + }, + Timestamp: 1718468882638019, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 4268615, + HostExecutionDurationMicros: 77, + CallerAddress: Guid_2 + }, + OnSetName: { + Args: { + Name: B + }, + Timestamp: 1718468882638019, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + }, + LogWarning: Deleting value that we don't have (no cached value available), + OnEvent: { + Timestamp: 1718468882638019, + CallerIdentity: (identity of B), + FunctionCall: { + Reducer: set_name, + ArgBytes: 0100000042, + RequestId: 1, + CallInfo: { + Args: { + Name: B + }, + Timestamp: 1718468882638019, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 4268615, + HostExecutionDurationMicros: 77, + CallerAddress: Guid_2 + }, + OnSetName: { + Args: { + Name: B + }, + Timestamp: 1718468882638019, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + }, + OnInsertMessage: { + message: { + sender: (identity of B), + sent: 1718468885695988, + text: Hello, A! + }, + reducerEvent: { + Args: { + Text: Hello, A! + }, + Timestamp: 1718468885695988, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718468885695988, + CallerIdentity: (identity of B), + FunctionCall: { + Reducer: send_message, + ArgBytes: 0900000048656C6C6F2C204121, + RequestId: 2, + CallInfo: { + Args: { + Text: Hello, A! + }, + Timestamp: 1718468885695988, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2677615, + HostExecutionDurationMicros: 46, + CallerAddress: Guid_2 + }, + OnSendMessage: { + Args: { + Text: Hello, A! + }, + Timestamp: 1718468885695988, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + }, + OnEvent: { + Timestamp: 1718468885695988, + CallerIdentity: (identity of B), + FunctionCall: { + Reducer: send_message, + ArgBytes: 0900000048656C6C6F2C204121, + RequestId: 2, + CallInfo: { + Args: { + Text: Hello, A! + }, + Timestamp: 1718468885695988, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2677615, + HostExecutionDurationMicros: 46, + CallerAddress: Guid_2 + }, + OnSendMessage: { + Args: { + Text: Hello, A! + }, + Timestamp: 1718468885695988, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + }, + OnInsertMessage: { + message: { + sender: (identity of A), + sent: 1718468889369867, + text: Hello, B! + }, + reducerEvent: { + Args: { + Text: Hello, B! + }, + Timestamp: 1718468889369867, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718468889369867, + CallerIdentity: (identity of A), + FunctionCall: { + Reducer: send_message, + ArgBytes: 0900000048656C6C6F2C204221, + RequestId: 3, + CallInfo: { + Args: { + Text: Hello, B! + }, + Timestamp: 1718468889369867, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2677615, + HostExecutionDurationMicros: 30, + CallerAddress: Guid_1 + }, + OnSendMessage: { + Args: { + Text: Hello, B! + }, + Timestamp: 1718468889369867, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + }, + OnEvent: { + Timestamp: 1718468889369867, + CallerIdentity: (identity of A), + FunctionCall: { + Reducer: send_message, + ArgBytes: 0900000048656C6C6F2C204221, + RequestId: 3, + CallInfo: { + Args: { + Text: Hello, B! + }, + Timestamp: 1718468889369867, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2677615, + HostExecutionDurationMicros: 30, + CallerAddress: Guid_1 + }, + OnSendMessage: { + Args: { + Text: Hello, B! + }, + Timestamp: 1718468889369867, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + }, + OnInsertMessage: { + message: { + sender: (identity of A), + sent: 1718468899752265, + text: Goodbye + }, + reducerEvent: { + Args: { + Text: Goodbye + }, + Timestamp: 1718468899752265, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718468899752265, + CallerIdentity: (identity of A), + FunctionCall: { + Reducer: send_message, + ArgBytes: 07000000476F6F64627965, + RequestId: 4, + CallInfo: { + Args: { + Text: Goodbye + }, + Timestamp: 1718468899752265, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2680615, + HostExecutionDurationMicros: 56, + CallerAddress: Guid_1 + }, + OnSendMessage: { + Args: { + Text: Goodbye + }, + Timestamp: 1718468899752265, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + }, + OnEvent: { + Timestamp: 1718468899752265, + CallerIdentity: (identity of A), + FunctionCall: { + Reducer: send_message, + ArgBytes: 07000000476F6F64627965, + RequestId: 4, + CallInfo: { + Args: { + Text: Goodbye + }, + Timestamp: 1718468899752265, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2680615, + HostExecutionDurationMicros: 56, + CallerAddress: Guid_1 + }, + OnSendMessage: { + Args: { + Text: Goodbye + }, + Timestamp: 1718468899752265, + Identity: (identity of A), + CallerAddress: Guid_1, + ErrMessage: + }, + LogException: Unknown reducer __identity_disconnected__ (Parameter 'Reducer'), + OnUpdateUser: { + oldUser: { + identity: (identity of A), + name: A, + online: true + }, + newUser: { + identity: (identity of A), + name: A, + online: false + } + }, + OnEvent: { + Timestamp: 1718468902123791, + CallerIdentity: (identity of A), + FunctionCall: { + Reducer: __identity_disconnected__, + ArgBytes: + }, + Message: , + EnergyQuantaUsed: 3595615, + HostExecutionDurationMicros: 63, + CallerAddress: Guid_1 + }, + OnInsertMessage: { + message: { + sender: (identity of B), + sent: 1718468904806316, + text: Goodbye + }, + reducerEvent: { + Args: { + Text: Goodbye + }, + Timestamp: 1718468904806316, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718468904806316, + CallerIdentity: (identity of B), + FunctionCall: { + Reducer: send_message, + ArgBytes: 07000000476F6F64627965, + RequestId: 3, + CallInfo: { + Args: { + Text: Goodbye + }, + Timestamp: 1718468904806316, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2680615, + HostExecutionDurationMicros: 41, + CallerAddress: Guid_2 + }, + OnSendMessage: { + Args: { + Text: Goodbye + }, + Timestamp: 1718468904806316, + Identity: (identity of B), + CallerAddress: Guid_2, + ErrMessage: + } + }, + FinalSnapshot: { + User: [ + { + identity: (identity of A), + name: A, + online: false + }, + { + identity: (identity of B), + name: B, + online: true + } + ], + Message: [ + { + sender: (identity of A), + sent: 1718468812745975, + text: Hello, world! + }, + { + sender: (identity of B), + sent: 1718468885695988, + text: Hello, A! + }, + { + sender: (identity of A), + sent: 1718468889369867, + text: Hello, B! + }, + { + sender: (identity of A), + sent: 1718468899752265, + text: Goodbye + }, + { + sender: (identity of B), + sent: 1718468904806316, + text: Goodbye + } + ] + } +} \ No newline at end of file diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs new file mode 100644 index 00000000000..1c69de3bf25 --- /dev/null +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -0,0 +1,156 @@ +namespace SpacetimeDB.Tests; + +using Google.Protobuf; +using SpacetimeDB.Types; +using Xunit; + +public class SnapshotTests +{ + class Events : List> + { + public void Add(string name, object? value = null) + { + base.Add(new(name, value)); + } + } + + class TestLogger(Events events) : ISpacetimeDBLogger + { + public void Log(string message) + { + events.Add("Log", message); + } + + public void LogWarning(string message) + { + // We don't start tracking in test simulation, so those warnings are expected. + if (message.StartsWith("Failed to finish tracking")) + { + return; + } + events.Add("LogWarning", message); + } + + public void LogError(string message) + { + events.Add("LogError", message); + } + + public void LogException(Exception e) + { + events.Add("LogException", e.Message); + } + } + + class EventsConverter : WriteOnlyJsonConverter + { + public override void Write(VerifyJsonWriter writer, Events events) + { + writer.WriteStartObject(); + foreach (var (name, value) in events) + { + writer.WriteMember(events, value, name); + } + writer.WriteEndObject(); + } + } + + [Fact] + public async Task VerifyAllTablesParsed() + { + // A dump of sample raw WebSocket messages. + var wsSamples = new[] + { + "i6SAKscCCiCXSrMbUY9G0LWbCv7nir3y2/TfbmCjMtzpw3Ori+vOphKQAmV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSkZVekkxTmlKOS5leUpvWlhoZmFXUmxiblJwZEhraU9pSTVOelJoWWpNeFlqVXhPR1kwTm1Rd1lqVTVZakJoWm1WbE56aGhZbVJtTW1SaVpqUmtaalpsTmpCaE16TXlaR05sT1dNek56TmhZamhpWldKalpXRTJJaXdpYVdGMElqb3hOekUzTlRJek1qTXhMQ0psZUhBaU9tNTFiR3g5LjNRZEpkc2tLdTRlamdZMXVvQmk3TTBQN1QyaXpaSEhITXhDcEpTRWROU1dEaXZzZ0FFdkZJUmZxVUFKY0J0U0txaEZPaXRiZHhIUVJKd3VaQV8wejdRGhBgfJ3DgQmutLQUG2NU/BhfAw==", + "ix6AEjwKNQiBIBIEVXNlchoqCAEaJiAAAACXSrMbUY9G0LWbCv7nir3y2/TfbmCjMtzpw3Ori+vOpgEBEAEYuwgD", + "i2WAIskBCloIzIrmlIPehgMSIJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mGhMKCHNldF9uYW1lEgUBAAAAQRgBMI+eiQI4kgFCEGB8ncOBCa60tBQbY1T8GF8SawpkCIEgEgRVc2VyGigaJiAAAACXSrMbUY9G0LWbCv7nir3y2/TfbmCjMtzpw3Ori+vOpgEBGi8IARorIAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAAEAAABBARABGLsQAw==", + "i2KAIsMBCmkI99mQmYPehgMSIJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mGiMKDHNlbmRfbWVzc2FnZRIRDQAAAEhlbGxvLCB3b3JsZCEYAjDfsrQBOCpCEGB8ncOBCa60tBQbY1T8GF8SVgpPCIIgEgdNZXNzYWdlGkEIARo9IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686m9ywkM/AaBgANAAAASGVsbG8sIHdvcmxkIRACGP8HAw==", + "C02AIpgBCl0I5obruIPehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGhgKFl9faWRlbnRpdHlfY29ubmVjdGVkX18w7713OEZCEJC8PImObEANVUiHlRorK9kSNwo1CIEgEgRVc2VyGioIARomIAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEAQED", + "i6SAKscCCiCrXZh0/QFd7A1Djg8nWK7VS0fdP9JieUyyQsAZp6Q3RBKQAmV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSkZVekkxTmlKOS5leUpvWlhoZmFXUmxiblJwZEhraU9pSmhZalZrT1RnM05HWmtNREUxWkdWak1HUTBNemhsTUdZeU56VTRZV1ZrTlRSaU5EZGtaRE5tWkRJMk1qYzVOR05pTWpReVl6QXhPV0UzWVRRek56UTBJaXdpYVdGMElqb3hOekU0TkRZNE9EYzVMQ0psZUhBaU9tNTFiR3g5LjNFWXQ1NkRpc2FBOUZfV0NOemhMSDU1LWh4TldNNEhQYjdQQi03OWx3Y2Ffcy1YSllBaXB2ZDlONmRXY2xYb3VmU0JyeXhuQlBkVTVsMHRoZHpoMmhBGhCQvDyJjmxADVVIh5UaKyvZAw==", + "C2CAEr4BCmYIgSASBFVzZXIaLwgBGisgAAAAl0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqYAAQAAAEEBGioIARomIAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEAQEKTwiCIBIHTWVzc2FnZRpBCAEaPSAAAACXSrMbUY9G0LWbCv7nir3y2/TfbmCjMtzpw3Ori+vOpvcsJDPwGgYADQAAAEhlbGxvLCB3b3JsZCEQARipAgM=", + "C2WAIsgBClkIw8m6uoPehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGhMKCHNldF9uYW1lEgUBAAAAQhgBMMfEhAI4TUIQkLw8iY5sQA1VSIeVGisr2RJrCmQIgSASBFVzZXIaKBomIAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEAQEaLwgBGisgAAAAq12YdP0BXewNQ44PJ1iu1UtH3T/SYnlMskLAGaekN0QAAQAAAEIBEAEYqgYD", + "C2WAIsgBClkIw8m6uoPehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGhMKCHNldF9uYW1lEgUBAAAAQhgBMMfEhAI4TUIQkLw8iY5sQA1VSIeVGisr2RJrCmQIgSASBFVzZXIaKBomIAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEAQEaLwgBGisgAAAAq12YdP0BXewNQ44PJ1iu1UtH3T/SYnlMskLAGaekN0QAAQAAAEIBEAEYqwYD", + "i16AIrsBCmUI9Jv1u4PehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGh8KDHNlbmRfbWVzc2FnZRINCQAAAEhlbGxvLCBBIRgCMO+2owE4LkIQkLw8iY5sQA1VSIeVGisr2RJSCksIgiASB01lc3NhZ2UaPQgBGjkgAAAAq12YdP0BXewNQ44PJ1iu1UtH3T/SYnlMskLAGaekN0T0TX038BoGAAkAAABIZWxsbywgQSEQAhi1BgM=", + "i16AIrsBCmUI9Jv1u4PehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGh8KDHNlbmRfbWVzc2FnZRINCQAAAEhlbGxvLCBBIRgCMO+2owE4LkIQkLw8iY5sQA1VSIeVGisr2RJSCksIgiASB01lc3NhZ2UaPQgBGjkgAAAAq12YdP0BXewNQ44PJ1iu1UtH3T/SYnlMskLAGaekN0T0TX038BoGAAkAAABIZWxsbywgQSEQAhjEBgM=", + "i16AIrsBCmUIi7rVvYPehgMSIJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mGh8KDHNlbmRfbWVzc2FnZRINCQAAAEhlbGxvLCBCIRgDMO+2owE4HkIQYHydw4EJrrS0FBtjVPwYXxJSCksIgiASB01lc3NhZ2UaPQgBGjkgAAAAl0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqYLXbU38BoGAAkAAABIZWxsbywgQiEQAxj6BQM=", + "i16AIrsBCmUIi7rVvYPehgMSIJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mGh8KDHNlbmRfbWVzc2FnZRINCQAAAEhlbGxvLCBCIRgDMO+2owE4HkIQYHydw4EJrrS0FBtjVPwYXxJSCksIgiASB01lc3NhZ2UaPQgBGjkgAAAAl0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqYLXbU38BoGAAkAAABIZWxsbywgQiEQAxjpBQM=", + "i1yAIrcBCmMIyZLPwoPehgMSIJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mGh0KDHNlbmRfbWVzc2FnZRILBwAAAEdvb2RieWUYBDCnzqMBODhCEGB8ncOBCa60tBQbY1T8GF8SUApJCIIgEgdNZXNzYWdlGjsIARo3IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mSclTOPAaBgAHAAAAR29vZGJ5ZRAEGNEJAw==", + "i1yAIrcBCmMIyZLPwoPehgMSIJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mGh0KDHNlbmRfbWVzc2FnZRILBwAAAEdvb2RieWUYBDCnzqMBODhCEGB8ncOBCa60tBQbY1T8GF8SUApJCIIgEgdNZXNzYWdlGjsIARo3IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mSclTOPAaBgAHAAAAR29vZGJ5ZRAEGOEJAw==", + "C2kAAICqqqrqXxTcD+p6clDwg7vaxcCvDg7uYCe/Obgf/OA3B3A/qzmY6UHBAdQB3OziAH4xcAA/uB/saAcHPzmAXxzAL25+cQA/2d3B7ubgdnRw8JuBHx0cHHIuLebjATHF4GDMGUquqzEiY+xnabR8rnJUD/pnbeD34suW/F/rW5Z8U2Xujcc7co6bz/3ANFLhXNpCudKdc1s61lQpYbnC5ryZXhPUaneL5mIXeYVTGJY0a/grczohEns6zY8cMWN1VtMBINjlExAAdBBrYMSiDjA=", + "i1yAIrcBCmMIrM+DxYPehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGh0KDHNlbmRfbWVzc2FnZRILBwAAAEdvb2RieWUYAzCnzqMBOClCEJC8PImObEANVUiHlRorK9kSUApJCIIgEgdNZXNzYWdlGjsIARo3IAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdErOegOPAaBgAHAAAAR29vZGJ5ZRADGIQGAw==", + }; + + var events = new Events(); + + Logger.Current = new TestLogger(events); + + var client = SpacetimeDBClient.instance; + + client.onBeforeSubscriptionApplied += () => events.Add("OnBeforeSubscriptionApplied"); + client.onEvent += (ev) => events.Add("OnEvent", ev); + client.onIdentityReceived += (_authToken, identity, address) => + events.Add("OnIdentityReceived", new { identity, address }); + client.onSubscriptionApplied += () => events.Add("OnSubscriptionApplied"); + client.onUnhandledReducerError += (exception) => + events.Add("OnUnhandledReducerError", exception); + + Reducer.OnSendMessageEvent += (reducerEvent, _text) => + events.Add("OnSendMessage", reducerEvent); + Reducer.OnSetNameEvent += (reducerEvent, _name) => events.Add("OnSetName", reducerEvent); + + User.OnDelete += (user, reducerEvent) => + events.Add("OnDeleteUser", new { user, reducerEvent }); + User.OnInsert += (user, reducerEvent) => + events.Add("OnInsertUser", new { user, reducerEvent }); + User.OnUpdate += (oldUser, newUser, reducerEvent) => + events.Add( + "OnUpdateUser", + new + { + oldUser, + newUser, + reducerEvent + } + ); + + Message.OnDelete += (message, reducerEvent) => + events.Add("OnDeleteMessage", new { message, reducerEvent }); + Message.OnInsert += (message, reducerEvent) => + events.Add("OnInsertMessage", new { message, reducerEvent }); + + // Simulate receiving WebSocket messages. + foreach (var wsSample in wsSamples) + { + client.OnMessageReceived(Convert.FromBase64String(wsSample), DateTime.UtcNow); + // Wait for this message to be picked up by the background thread, preprocessed and stored in the preprocessed queue. + // Otherwise we'll get inconsistent output order between test reruns. + while (!client.HasPreProcessedMessage) { } + // Once the message is in the preprocessed queue, we can invoke Update() to handle events on the main thread. + client.Update(); + } + + // Verify dumped events and the final client state. + await Verify( + new + { + Events = events, + FinalSnapshot = new + { + User = User.Iter().ToList(), + Message = Message.Iter().ToList() + } + } + ) + .AddExtraSettings(settings => settings.Converters.Add(new EventsConverter())) + .ScrubLinesWithReplace(s => + s.Replace( + "974AB31B518F46D0B59B0AFEE78ABDF2DBF4DF6E60A332DCE9C373AB8BEBCEA6", + "(identity of A)" + ) + .Replace( + "AB5D9874FD015DEC0D438E0F2758AED54B47DD3FD262794CB242C019A7A43744", + "(identity of B)" + ) + ); + } +} diff --git a/sdks/csharp/tests/VerifyInit.cs b/sdks/csharp/tests/VerifyInit.cs new file mode 100644 index 00000000000..530f413f89b --- /dev/null +++ b/sdks/csharp/tests/VerifyInit.cs @@ -0,0 +1,44 @@ +namespace SpacetimeDB.Tests; + +using System.Runtime.CompilerServices; +using Google.Protobuf; +using SpacetimeDB.Types; + +public static class VerifyInit +{ + class ByteStringConverter : WriteOnlyJsonConverter + { + public override void Write(VerifyJsonWriter writer, ByteString value) + { + writer.WriteValue(Convert.ToHexString(value.Span)); + } + } + + class IdentityOrAddressConverter : WriteOnlyJsonConverter + { + public override bool CanConvert(Type objectType) + { + objectType = Nullable.GetUnderlyingType(objectType) ?? objectType; + return objectType == typeof(Identity) || objectType == typeof(Address); + } + + public override void Write(VerifyJsonWriter writer, object value) + { + writer.WriteValue(value.ToString()); + } + } + + [ModuleInitializer] + public static void Init() + { + Environment.SetEnvironmentVariable("DiffEngine_TargetOnLeft", "true"); + + VerifierSettings.AddExtraSettings(settings => + settings.Converters.AddRange( + [new ByteStringConverter(), new IdentityOrAddressConverter()] + ) + ); + + VerifierSettings.IgnoreMember(_ => _.ReducerName); + } +} diff --git a/sdks/csharp/tests/tests.csproj b/sdks/csharp/tests/tests.csproj new file mode 100644 index 00000000000..30b5def6ee5 --- /dev/null +++ b/sdks/csharp/tests/tests.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + From 40f6138c4ccf25c0fdd64a9ea53699e8cd287934 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 15 Jun 2024 22:08:20 +0100 Subject: [PATCH 087/223] Update API docs --- sdks/csharp/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 44e63351088..82c2fc47aad 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -114,9 +114,11 @@ The client cache is a local cache of the data that the client has received from When you run the CLI generate command, SpacetimeDB will automatically generate a class for each table in your database. These classes are generated in the `SpacetimeDB.Types` namespace. Each class contains a set of static methods that allow you to query the client cache. The following methods are available: -- `FilterByCOLUMN`: Filters the table by the specified column value. -- `Iter`: Returns an iterator over the table. -- `Count`: Returns the number of rows in the table. +- `int Count()`: Returns the number of rows in the table. +- `IEnumerable Iter()`: Returns an iterator over the table. +- `IEnumerable FilterByCOLUMN(ColumnValue)`: Filters the table by the specified column value. +- `TableRow? FindByCOLUMN(ColumnValue)`: Finds a single item by the specifed column value. +- `IEnumerable Query(Func)`: Filters the table with the specified predicate. ### Calling Reducers From 17ce57ffe143c63d840fb4230ad65c1100d7e7d1 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 15 Jun 2024 23:24:15 +0100 Subject: [PATCH 088/223] Store test dump in a maintainable format --- ...otTests.VerifyAllTablesParsed.verified.txt | 427 +++++------------- sdks/csharp/tests/SnapshotTests.cs | 99 ++-- sdks/csharp/tests/VerifyInit.cs | 38 +- sdks/csharp/tests/sample-dump.jsonl | 10 + 4 files changed, 224 insertions(+), 350 deletions(-) create mode 100644 sdks/csharp/tests/sample-dump.jsonl diff --git a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt index 66e66a98620..bc7a86c4161 100644 --- a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -10,6 +10,25 @@ online: true } }, + LogException: Unknown reducer __identity_connected__ (Parameter 'Reducer'), + OnInsertUser: { + user: { + identity: (identity of B), + online: true + } + }, + OnEvent: { + Timestamp: 1718487763059031, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: __identity_connected__, + ArgBytes: + }, + Message: , + EnergyQuantaUsed: 1957615, + HostExecutionDurationMicros: 66, + CallerAddress: Guid_2 + }, OnUpdateUser: { oldUser: { identity: (identity of A), @@ -24,15 +43,15 @@ Args: { Name: A }, - Timestamp: 1718468803659084, + Timestamp: 1718487768057579, Identity: (identity of A), CallerAddress: Guid_1, ErrMessage: } }, OnEvent: { - Timestamp: 1718468803659084, - CallerIdentity: (identity of A), + Timestamp: 1718487768057579, + CallerIdentity: {Scrubbed}, FunctionCall: { Reducer: set_name, ArgBytes: 0100000041, @@ -41,7 +60,7 @@ Args: { Name: A }, - Timestamp: 1718468803659084, + Timestamp: 1718487768057579, Identity: (identity of A), CallerAddress: Guid_1, ErrMessage: @@ -49,88 +68,65 @@ }, Message: , EnergyQuantaUsed: 4345615, - HostExecutionDurationMicros: 146, + HostExecutionDurationMicros: 70, CallerAddress: Guid_1 }, OnSetName: { Args: { Name: A }, - Timestamp: 1718468803659084, + Timestamp: 1718487768057579, Identity: (identity of A), CallerAddress: Guid_1, ErrMessage: }, OnInsertMessage: { message: { - sender: (identity of A), - sent: 1718468812745975, - text: Hello, world! + sender: (identity of B), + sent: 1718487775346381, + text: Hello, A! }, reducerEvent: { Args: { - Text: Hello, world! + Text: Hello, A! }, - Timestamp: 1718468812745975, - Identity: (identity of A), - CallerAddress: Guid_1, + Timestamp: 1718487775346381, + Identity: (identity of B), + CallerAddress: Guid_2, ErrMessage: } }, OnEvent: { - Timestamp: 1718468812745975, - CallerIdentity: (identity of A), + Timestamp: 1718487775346381, + CallerIdentity: {Scrubbed}, FunctionCall: { Reducer: send_message, - ArgBytes: 0D00000048656C6C6F2C20776F726C6421, - RequestId: 2, + ArgBytes: 0900000048656C6C6F2C204121, + RequestId: 1, CallInfo: { Args: { - Text: Hello, world! + Text: Hello, A! }, - Timestamp: 1718468812745975, - Identity: (identity of A), - CallerAddress: Guid_1, + Timestamp: 1718487775346381, + Identity: (identity of B), + CallerAddress: Guid_2, ErrMessage: } }, Message: , - EnergyQuantaUsed: 2955615, - HostExecutionDurationMicros: 42, - CallerAddress: Guid_1 + EnergyQuantaUsed: 2779615, + HostExecutionDurationMicros: 57, + CallerAddress: Guid_2 }, OnSendMessage: { Args: { - Text: Hello, world! + Text: Hello, A! }, - Timestamp: 1718468812745975, - Identity: (identity of A), - CallerAddress: Guid_1, + Timestamp: 1718487775346381, + Identity: (identity of B), + CallerAddress: Guid_2, ErrMessage: }, - LogException: Unknown reducer __identity_connected__ (Parameter 'Reducer'), - OnInsertUser: { - user: { - identity: (identity of B), - online: true - } - }, - OnEvent: { - Timestamp: 1718468879237990, - CallerIdentity: (identity of B), - FunctionCall: { - Reducer: __identity_connected__, - ArgBytes: - }, - Message: , - EnergyQuantaUsed: 1957615, - HostExecutionDurationMicros: 70, - CallerAddress: Guid_2 - }, - OnIdentityReceived: { - identity: (identity of B), - address: Guid_2 - }, OnUpdateUser: { oldUser: { identity: (identity of B), @@ -145,56 +141,24 @@ Args: { Name: B }, - Timestamp: 1718468882638019, + Timestamp: 1718487777307855, Identity: (identity of B), CallerAddress: Guid_2, ErrMessage: } }, OnEvent: { - Timestamp: 1718468882638019, - CallerIdentity: (identity of B), - FunctionCall: { - Reducer: set_name, - ArgBytes: 0100000042, - RequestId: 1, - CallInfo: { - Args: { - Name: B - }, - Timestamp: 1718468882638019, - Identity: (identity of B), - CallerAddress: Guid_2, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 4268615, - HostExecutionDurationMicros: 77, - CallerAddress: Guid_2 - }, - OnSetName: { - Args: { - Name: B - }, - Timestamp: 1718468882638019, - Identity: (identity of B), - CallerAddress: Guid_2, - ErrMessage: - }, - LogWarning: Deleting value that we don't have (no cached value available), - OnEvent: { - Timestamp: 1718468882638019, - CallerIdentity: (identity of B), + Timestamp: 1718487777307855, + CallerIdentity: {Scrubbed}, FunctionCall: { Reducer: set_name, ArgBytes: 0100000042, - RequestId: 1, + RequestId: 2, CallInfo: { Args: { Name: B }, - Timestamp: 1718468882638019, + Timestamp: 1718487777307855, Identity: (identity of B), CallerAddress: Guid_2, ErrMessage: @@ -202,92 +166,14 @@ }, Message: , EnergyQuantaUsed: 4268615, - HostExecutionDurationMicros: 77, + HostExecutionDurationMicros: 98, CallerAddress: Guid_2 }, OnSetName: { Args: { Name: B }, - Timestamp: 1718468882638019, - Identity: (identity of B), - CallerAddress: Guid_2, - ErrMessage: - }, - OnInsertMessage: { - message: { - sender: (identity of B), - sent: 1718468885695988, - text: Hello, A! - }, - reducerEvent: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718468885695988, - Identity: (identity of B), - CallerAddress: Guid_2, - ErrMessage: - } - }, - OnEvent: { - Timestamp: 1718468885695988, - CallerIdentity: (identity of B), - FunctionCall: { - Reducer: send_message, - ArgBytes: 0900000048656C6C6F2C204121, - RequestId: 2, - CallInfo: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718468885695988, - Identity: (identity of B), - CallerAddress: Guid_2, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 2677615, - HostExecutionDurationMicros: 46, - CallerAddress: Guid_2 - }, - OnSendMessage: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718468885695988, - Identity: (identity of B), - CallerAddress: Guid_2, - ErrMessage: - }, - OnEvent: { - Timestamp: 1718468885695988, - CallerIdentity: (identity of B), - FunctionCall: { - Reducer: send_message, - ArgBytes: 0900000048656C6C6F2C204121, - RequestId: 2, - CallInfo: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718468885695988, - Identity: (identity of B), - CallerAddress: Guid_2, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 2677615, - HostExecutionDurationMicros: 46, - CallerAddress: Guid_2 - }, - OnSendMessage: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718468885695988, + Timestamp: 1718487777307855, Identity: (identity of B), CallerAddress: Guid_2, ErrMessage: @@ -295,62 +181,31 @@ OnInsertMessage: { message: { sender: (identity of A), - sent: 1718468889369867, + sent: 1718487783175083, text: Hello, B! }, reducerEvent: { Args: { Text: Hello, B! }, - Timestamp: 1718468889369867, + Timestamp: 1718487783175083, Identity: (identity of A), CallerAddress: Guid_1, ErrMessage: } }, OnEvent: { - Timestamp: 1718468889369867, - CallerIdentity: (identity of A), - FunctionCall: { - Reducer: send_message, - ArgBytes: 0900000048656C6C6F2C204221, - RequestId: 3, - CallInfo: { - Args: { - Text: Hello, B! - }, - Timestamp: 1718468889369867, - Identity: (identity of A), - CallerAddress: Guid_1, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 2677615, - HostExecutionDurationMicros: 30, - CallerAddress: Guid_1 - }, - OnSendMessage: { - Args: { - Text: Hello, B! - }, - Timestamp: 1718468889369867, - Identity: (identity of A), - CallerAddress: Guid_1, - ErrMessage: - }, - OnEvent: { - Timestamp: 1718468889369867, - CallerIdentity: (identity of A), + Timestamp: 1718487783175083, + CallerIdentity: {Scrubbed}, FunctionCall: { Reducer: send_message, ArgBytes: 0900000048656C6C6F2C204221, - RequestId: 3, + RequestId: 2, CallInfo: { Args: { Text: Hello, B! }, - Timestamp: 1718468889369867, + Timestamp: 1718487783175083, Identity: (identity of A), CallerAddress: Guid_1, ErrMessage: @@ -358,166 +213,135 @@ }, Message: , EnergyQuantaUsed: 2677615, - HostExecutionDurationMicros: 30, + HostExecutionDurationMicros: 40, CallerAddress: Guid_1 }, OnSendMessage: { Args: { Text: Hello, B! }, - Timestamp: 1718468889369867, + Timestamp: 1718487783175083, Identity: (identity of A), CallerAddress: Guid_1, ErrMessage: }, OnInsertMessage: { message: { - sender: (identity of A), - sent: 1718468899752265, - text: Goodbye + sender: (identity of B), + sent: 1718487787645364, + text: Goodbye! }, reducerEvent: { Args: { - Text: Goodbye + Text: Goodbye! }, - Timestamp: 1718468899752265, - Identity: (identity of A), - CallerAddress: Guid_1, + Timestamp: 1718487787645364, + Identity: (identity of B), + CallerAddress: Guid_2, ErrMessage: } }, OnEvent: { - Timestamp: 1718468899752265, - CallerIdentity: (identity of A), - FunctionCall: { - Reducer: send_message, - ArgBytes: 07000000476F6F64627965, - RequestId: 4, - CallInfo: { - Args: { - Text: Goodbye - }, - Timestamp: 1718468899752265, - Identity: (identity of A), - CallerAddress: Guid_1, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 2680615, - HostExecutionDurationMicros: 56, - CallerAddress: Guid_1 - }, - OnSendMessage: { - Args: { - Text: Goodbye - }, - Timestamp: 1718468899752265, - Identity: (identity of A), - CallerAddress: Guid_1, - ErrMessage: - }, - OnEvent: { - Timestamp: 1718468899752265, - CallerIdentity: (identity of A), + Timestamp: 1718487787645364, + CallerIdentity: {Scrubbed}, FunctionCall: { Reducer: send_message, - ArgBytes: 07000000476F6F64627965, - RequestId: 4, + ArgBytes: 08000000476F6F6462796521, + RequestId: 3, CallInfo: { Args: { - Text: Goodbye + Text: Goodbye! }, - Timestamp: 1718468899752265, - Identity: (identity of A), - CallerAddress: Guid_1, + Timestamp: 1718487787645364, + Identity: (identity of B), + CallerAddress: Guid_2, ErrMessage: } }, Message: , - EnergyQuantaUsed: 2680615, - HostExecutionDurationMicros: 56, - CallerAddress: Guid_1 + EnergyQuantaUsed: 2636615, + HostExecutionDurationMicros: 28, + CallerAddress: Guid_2 }, OnSendMessage: { Args: { - Text: Goodbye + Text: Goodbye! }, - Timestamp: 1718468899752265, - Identity: (identity of A), - CallerAddress: Guid_1, + Timestamp: 1718487787645364, + Identity: (identity of B), + CallerAddress: Guid_2, ErrMessage: }, LogException: Unknown reducer __identity_disconnected__ (Parameter 'Reducer'), OnUpdateUser: { oldUser: { - identity: (identity of A), - name: A, + identity: (identity of B), + name: B, online: true }, newUser: { - identity: (identity of A), - name: A, + identity: (identity of B), + name: B, online: false } }, OnEvent: { - Timestamp: 1718468902123791, - CallerIdentity: (identity of A), + Timestamp: 1718487791901504, + CallerIdentity: {Scrubbed}, FunctionCall: { Reducer: __identity_disconnected__, ArgBytes: }, Message: , EnergyQuantaUsed: 3595615, - HostExecutionDurationMicros: 63, - CallerAddress: Guid_1 + HostExecutionDurationMicros: 75, + CallerAddress: Guid_2 }, OnInsertMessage: { message: { - sender: (identity of B), - sent: 1718468904806316, - text: Goodbye + sender: (identity of A), + sent: 1718487794937841, + text: Goodbye! }, reducerEvent: { Args: { - Text: Goodbye + Text: Goodbye! }, - Timestamp: 1718468904806316, - Identity: (identity of B), - CallerAddress: Guid_2, + Timestamp: 1718487794937841, + Identity: (identity of A), + CallerAddress: Guid_1, ErrMessage: } }, OnEvent: { - Timestamp: 1718468904806316, - CallerIdentity: (identity of B), + Timestamp: 1718487794937841, + CallerIdentity: {Scrubbed}, FunctionCall: { Reducer: send_message, - ArgBytes: 07000000476F6F64627965, + ArgBytes: 08000000476F6F6462796521, RequestId: 3, CallInfo: { Args: { - Text: Goodbye + Text: Goodbye! }, - Timestamp: 1718468904806316, - Identity: (identity of B), - CallerAddress: Guid_2, + Timestamp: 1718487794937841, + Identity: (identity of A), + CallerAddress: Guid_1, ErrMessage: } }, Message: , - EnergyQuantaUsed: 2680615, - HostExecutionDurationMicros: 41, - CallerAddress: Guid_2 + EnergyQuantaUsed: 2636615, + HostExecutionDurationMicros: 34, + CallerAddress: Guid_1 }, OnSendMessage: { Args: { - Text: Goodbye + Text: Goodbye! }, - Timestamp: 1718468904806316, - Identity: (identity of B), - CallerAddress: Guid_2, + Timestamp: 1718487794937841, + Identity: (identity of A), + CallerAddress: Guid_1, ErrMessage: } }, @@ -526,39 +350,34 @@ { identity: (identity of A), name: A, - online: false + online: true }, { identity: (identity of B), name: B, - online: true + online: false } ], Message: [ - { - sender: (identity of A), - sent: 1718468812745975, - text: Hello, world! - }, { sender: (identity of B), - sent: 1718468885695988, + sent: 1718487775346381, text: Hello, A! }, { sender: (identity of A), - sent: 1718468889369867, + sent: 1718487783175083, text: Hello, B! }, { - sender: (identity of A), - sent: 1718468899752265, - text: Goodbye + sender: (identity of B), + sent: 1718487787645364, + text: Goodbye! }, { - sender: (identity of B), - sent: 1718468904806316, - text: Goodbye + sender: (identity of A), + sent: 1718487794937841, + text: Goodbye! } ] } diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs index 1c69de3bf25..c83b3af070a 100644 --- a/sdks/csharp/tests/SnapshotTests.cs +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -1,5 +1,8 @@ namespace SpacetimeDB.Tests; +using System.IO.Compression; +using System.Runtime.CompilerServices; +using Argon; using Google.Protobuf; using SpacetimeDB.Types; using Xunit; @@ -55,41 +58,78 @@ public override void Write(VerifyJsonWriter writer, Events events) } } + class ByteStringReaderConverter : JsonConverter + { + public override ByteString ReadJson( + JsonReader reader, + Type type, + ByteString? existingValue, + bool hasExisting, + JsonSerializer serializer + ) + { + var s = reader.StringValue; + try + { + return ByteString.FromBase64(s); + } + catch + { + return ByteString.CopyFromUtf8(s); + } + } + + public override void WriteJson( + JsonWriter writer, + ByteString value, + JsonSerializer serializer + ) + { + throw new NotImplementedException(); + } + } + + private static string GetTestDir([CallerFilePath] string testFilePath = "") => + Path.GetDirectoryName(testFilePath)!; + [Fact] public async Task VerifyAllTablesParsed() { - // A dump of sample raw WebSocket messages. - var wsSamples = new[] + var settings = new JsonSerializerSettings { - "i6SAKscCCiCXSrMbUY9G0LWbCv7nir3y2/TfbmCjMtzpw3Ori+vOphKQAmV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSkZVekkxTmlKOS5leUpvWlhoZmFXUmxiblJwZEhraU9pSTVOelJoWWpNeFlqVXhPR1kwTm1Rd1lqVTVZakJoWm1WbE56aGhZbVJtTW1SaVpqUmtaalpsTmpCaE16TXlaR05sT1dNek56TmhZamhpWldKalpXRTJJaXdpYVdGMElqb3hOekUzTlRJek1qTXhMQ0psZUhBaU9tNTFiR3g5LjNRZEpkc2tLdTRlamdZMXVvQmk3TTBQN1QyaXpaSEhITXhDcEpTRWROU1dEaXZzZ0FFdkZJUmZxVUFKY0J0U0txaEZPaXRiZHhIUVJKd3VaQV8wejdRGhBgfJ3DgQmutLQUG2NU/BhfAw==", - "ix6AEjwKNQiBIBIEVXNlchoqCAEaJiAAAACXSrMbUY9G0LWbCv7nir3y2/TfbmCjMtzpw3Ori+vOpgEBEAEYuwgD", - "i2WAIskBCloIzIrmlIPehgMSIJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mGhMKCHNldF9uYW1lEgUBAAAAQRgBMI+eiQI4kgFCEGB8ncOBCa60tBQbY1T8GF8SawpkCIEgEgRVc2VyGigaJiAAAACXSrMbUY9G0LWbCv7nir3y2/TfbmCjMtzpw3Ori+vOpgEBGi8IARorIAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAAEAAABBARABGLsQAw==", - "i2KAIsMBCmkI99mQmYPehgMSIJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mGiMKDHNlbmRfbWVzc2FnZRIRDQAAAEhlbGxvLCB3b3JsZCEYAjDfsrQBOCpCEGB8ncOBCa60tBQbY1T8GF8SVgpPCIIgEgdNZXNzYWdlGkEIARo9IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686m9ywkM/AaBgANAAAASGVsbG8sIHdvcmxkIRACGP8HAw==", - "C02AIpgBCl0I5obruIPehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGhgKFl9faWRlbnRpdHlfY29ubmVjdGVkX18w7713OEZCEJC8PImObEANVUiHlRorK9kSNwo1CIEgEgRVc2VyGioIARomIAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEAQED", - "i6SAKscCCiCrXZh0/QFd7A1Djg8nWK7VS0fdP9JieUyyQsAZp6Q3RBKQAmV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSkZVekkxTmlKOS5leUpvWlhoZmFXUmxiblJwZEhraU9pSmhZalZrT1RnM05HWmtNREUxWkdWak1HUTBNemhsTUdZeU56VTRZV1ZrTlRSaU5EZGtaRE5tWkRJMk1qYzVOR05pTWpReVl6QXhPV0UzWVRRek56UTBJaXdpYVdGMElqb3hOekU0TkRZNE9EYzVMQ0psZUhBaU9tNTFiR3g5LjNFWXQ1NkRpc2FBOUZfV0NOemhMSDU1LWh4TldNNEhQYjdQQi03OWx3Y2Ffcy1YSllBaXB2ZDlONmRXY2xYb3VmU0JyeXhuQlBkVTVsMHRoZHpoMmhBGhCQvDyJjmxADVVIh5UaKyvZAw==", - "C2CAEr4BCmYIgSASBFVzZXIaLwgBGisgAAAAl0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqYAAQAAAEEBGioIARomIAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEAQEKTwiCIBIHTWVzc2FnZRpBCAEaPSAAAACXSrMbUY9G0LWbCv7nir3y2/TfbmCjMtzpw3Ori+vOpvcsJDPwGgYADQAAAEhlbGxvLCB3b3JsZCEQARipAgM=", - "C2WAIsgBClkIw8m6uoPehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGhMKCHNldF9uYW1lEgUBAAAAQhgBMMfEhAI4TUIQkLw8iY5sQA1VSIeVGisr2RJrCmQIgSASBFVzZXIaKBomIAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEAQEaLwgBGisgAAAAq12YdP0BXewNQ44PJ1iu1UtH3T/SYnlMskLAGaekN0QAAQAAAEIBEAEYqgYD", - "C2WAIsgBClkIw8m6uoPehgMSIKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEGhMKCHNldF9uYW1lEgUBAAAAQhgBMMfEhAI4TUIQkLw8iY5sQA1VSIeVGisr2RJrCmQIgSASBFVzZXIaKBomIAAAAKtdmHT9AV3sDUOODydYrtVLR90/0mJ5TLJCwBmnpDdEAQEaLwgBGisgAAAAq12YdP0BXewNQ44PJ1iu1UtH3T/SYnlMskLAGaekN0QAAQAAAEIBEAEYqwYD", - "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", + Converters = [new ByteStringReaderConverter()] }; + // We store the dump in JSON-NL format for simplicity (it's just `ClientApi.Message.toString()`) and readability. + var sampleDumpParsed = File.ReadLines(Path.Combine(GetTestDir(), "sample-dump.jsonl")) + .Select(line => JsonConvert.DeserializeObject(line, settings)); + + // But for proper testing we need to convert it back to raw binary messages as if it was received over network. + var sampleDumpBinary = sampleDumpParsed.Select(message => + { + using var output = new MemoryStream(); + using (var brotli = new BrotliStream(output, CompressionMode.Compress)) + { + message.WriteTo(brotli); + } + return output.ToArray(); + }); + var events = new Events(); Logger.Current = new TestLogger(events); var client = SpacetimeDBClient.instance; + Identity? myIdentity = null; + client.onBeforeSubscriptionApplied += () => events.Add("OnBeforeSubscriptionApplied"); client.onEvent += (ev) => events.Add("OnEvent", ev); client.onIdentityReceived += (_authToken, identity, address) => + { + myIdentity = identity; events.Add("OnIdentityReceived", new { identity, address }); + }; client.onSubscriptionApplied += () => events.Add("OnSubscriptionApplied"); client.onUnhandledReducerError += (exception) => events.Add("OnUnhandledReducerError", exception); @@ -119,9 +159,9 @@ public async Task VerifyAllTablesParsed() events.Add("OnInsertMessage", new { message, reducerEvent }); // Simulate receiving WebSocket messages. - foreach (var wsSample in wsSamples) + foreach (var sample in sampleDumpBinary) { - client.OnMessageReceived(Convert.FromBase64String(wsSample), DateTime.UtcNow); + client.OnMessageReceived(sample, DateTime.UtcNow); // Wait for this message to be picked up by the background thread, preprocessed and stored in the preprocessed queue. // Otherwise we'll get inconsistent output order between test reruns. while (!client.HasPreProcessedMessage) { } @@ -141,16 +181,11 @@ await Verify( } } ) - .AddExtraSettings(settings => settings.Converters.Add(new EventsConverter())) - .ScrubLinesWithReplace(s => - s.Replace( - "974AB31B518F46D0B59B0AFEE78ABDF2DBF4DF6E60A332DCE9C373AB8BEBCEA6", - "(identity of A)" - ) - .Replace( - "AB5D9874FD015DEC0D438E0F2758AED54B47DD3FD262794CB242C019A7A43744", - "(identity of B)" - ) - ); + .AddExtraSettings(settings => + settings.Converters.AddRange( + [new EventsConverter(), new IdentityConverter(myIdentity)] + ) + ) + .ScrubMember(_ => _.CallerIdentity); } } diff --git a/sdks/csharp/tests/VerifyInit.cs b/sdks/csharp/tests/VerifyInit.cs index 530f413f89b..3410dd136ce 100644 --- a/sdks/csharp/tests/VerifyInit.cs +++ b/sdks/csharp/tests/VerifyInit.cs @@ -4,30 +4,40 @@ namespace SpacetimeDB.Tests; using Google.Protobuf; using SpacetimeDB.Types; -public static class VerifyInit +class ByteStringConverter : WriteOnlyJsonConverter { - class ByteStringConverter : WriteOnlyJsonConverter + public override void Write(VerifyJsonWriter writer, ByteString value) { - public override void Write(VerifyJsonWriter writer, ByteString value) - { - writer.WriteValue(Convert.ToHexString(value.Span)); - } + writer.WriteValue(Convert.ToHexString(value.Span)); } +} - class IdentityOrAddressConverter : WriteOnlyJsonConverter +// A converter that scrubs identity to a stable string. +public class IdentityConverter(Identity? myIdentity) : WriteOnlyJsonConverter +{ + public override void Write(VerifyJsonWriter writer, Identity value) { - public override bool CanConvert(Type objectType) + if (value == myIdentity) { - objectType = Nullable.GetUnderlyingType(objectType) ?? objectType; - return objectType == typeof(Identity) || objectType == typeof(Address); + writer.WriteValue("(identity of A)"); } - - public override void Write(VerifyJsonWriter writer, object value) + else { - writer.WriteValue(value.ToString()); + writer.WriteValue("(identity of B)"); } } +} + +class AddressConverter : WriteOnlyJsonConverter
    +{ + public override void Write(VerifyJsonWriter writer, Address value) + { + writer.WriteValue(value.ToString()); + } +} +static class VerifyInit +{ [ModuleInitializer] public static void Init() { @@ -35,7 +45,7 @@ public static void Init() VerifierSettings.AddExtraSettings(settings => settings.Converters.AddRange( - [new ByteStringConverter(), new IdentityOrAddressConverter()] + [new ByteStringConverter(), new AddressConverter()] ) ); diff --git a/sdks/csharp/tests/sample-dump.jsonl b/sdks/csharp/tests/sample-dump.jsonl new file mode 100644 index 00000000000..67032dc20d7 --- /dev/null +++ b/sdks/csharp/tests/sample-dump.jsonl @@ -0,0 +1,10 @@ +{ "identityToken": { "identity": "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiI4ZjkwY2M5NGE5OTY4ZGY2ZDI5N2JhYTY2NTAzYTg5M2IxYzM0YjBiMDAyNjhhNTE0ODk4ZGQ5NTRiMGRhMjBiIiwiaWF0IjoxNzE4NDg3NjY4LCJleHAiOm51bGx9.PSn481bLRqtFwIh46nOXDY14X3GKbz8t4K4GmBmz50loU6xzeL7zDdCh1V2cmiQsoGq8Erxg0r_6b6Y5SqKoBA", "address": "Vd4dFzcEzhLHJ6uNL8VXFg==" } } +{ "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaILAQE=" } ] } ], "requestId": 1, "totalHostExecutionDurationMicros": "366" } } +{ "transactionUpdate": { "event": { "timestamp": "1718487763059031", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "__identity_connected__" }, "energyQuantaUsed": "1957615", "hostExecutionDurationMicros": "66", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAQE=" } ] } ] } } } +{ "transactionUpdate": { "event": { "timestamp": "1718487768057579", "callerIdentity": "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "functionCall": { "reducer": "set_name", "argBytes": "AQAAAEE=", "requestId": 1 }, "energyQuantaUsed": "4345615", "hostExecutionDurationMicros": "70", "callerAddress": "Vd4dFzcEzhLHJ6uNL8VXFg==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaILAQE=" }, { "op": "INSERT", "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaILAAEAAABBAQ==" } ] } ], "requestId": 1, "totalHostExecutionDurationMicros": "1239" } } } +{ "transactionUpdate": { "event": { "timestamp": "1718487775346381", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "send_message", "argBytes": "CQAAAEhlbGxvLCBBIQ==", "requestId": 1 }, "energyQuantaUsed": "2779615", "hostExecutionDurationMicros": "57", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4098, "tableName": "Message", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mzX5mnfQaBgAJAAAASGVsbG8sIEEh" } ] } ], "requestId": 1, "totalHostExecutionDurationMicros": "793" } } } +{ "transactionUpdate": { "event": { "timestamp": "1718487777307855", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "set_name", "argBytes": "AQAAAEI=", "requestId": 2 }, "energyQuantaUsed": "4268615", "hostExecutionDurationMicros": "98", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAQE=" }, { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAAEAAABCAQ==" } ] } ], "requestId": 2, "totalHostExecutionDurationMicros": "1317" } } } +{ "transactionUpdate": { "event": { "timestamp": "1718487783175083", "callerIdentity": "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "functionCall": { "reducer": "send_message", "argBytes": "CQAAAEhlbGxvLCBCIQ==", "requestId": 2 }, "energyQuantaUsed": "2677615", "hostExecutionDurationMicros": "40", "callerAddress": "Vd4dFzcEzhLHJ6uNL8VXFg==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4098, "tableName": "Message", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaILq/PdnfQaBgAJAAAASGVsbG8sIEIh" } ] } ], "requestId": 2, "totalHostExecutionDurationMicros": "676" } } } +{ "transactionUpdate": { "event": { "timestamp": "1718487787645364", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "send_message", "argBytes": "CAAAAEdvb2RieWUh", "requestId": 3 }, "energyQuantaUsed": "2636615", "hostExecutionDurationMicros": "28", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4098, "tableName": "Message", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mtCkinvQaBgAIAAAAR29vZGJ5ZSE=" } ] } ], "requestId": 3, "totalHostExecutionDurationMicros": "569" } } } +{ "transactionUpdate": { "event": { "timestamp": "1718487791901504", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "__identity_disconnected__" }, "energyQuantaUsed": "3595615", "hostExecutionDurationMicros": "75", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAAEAAABCAQ==" }, { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAAEAAABCAA==" } ] } ] } } } +{ "transactionUpdate": { "event": { "timestamp": "1718487794937841", "callerIdentity": "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "functionCall": { "reducer": "send_message", "argBytes": "CAAAAEdvb2RieWUh", "requestId": 3 }, "energyQuantaUsed": "2636615", "hostExecutionDurationMicros": "34", "callerAddress": "Vd4dFzcEzhLHJ6uNL8VXFg==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4098, "tableName": "Message", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaIL8W+RnvQaBgAIAAAAR29vZGJ5ZSE=" } ] } ], "requestId": 3, "totalHostExecutionDurationMicros": "1072" } } } From 21e475b1cc7cbc59e4d3f011c795edec9480030f Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 15 Jun 2024 23:40:38 +0100 Subject: [PATCH 089/223] Add Stats snapshot --- ...otTests.VerifyAllTablesParsed.verified.txt | 24 ++++++++++ sdks/csharp/tests/SnapshotTests.cs | 48 ++++++++++++------- sdks/csharp/tests/VerifyInit.cs | 28 +++++++++++ 3 files changed, 84 insertions(+), 16 deletions(-) diff --git a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt index bc7a86c4161..fdcf9eb110a 100644 --- a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -380,5 +380,29 @@ text: Goodbye! } ] + }, + Stats: { + ReducerRequestTracker: { + sampleCount: 3, + requestsAwaitingResponse: 5, + Min: sample#4, + Max: sample#2 + }, + OneOffRequestTracker: {}, + SubscriptionRequestTracker: { + sampleCount: 1, + Min: sample#1, + Max: sample#1 + }, + AllReducersTracker: { + sampleCount: 8, + Min: reducer=send_message, + Max: reducer=set_name + }, + ParseMessageTracker: { + sampleCount: 9, + Min: type=TransactionUpdate,reducer=send_message, + Max: type=SubscriptionUpdate + } } } \ No newline at end of file diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs index c83b3af070a..29b20a30379 100644 --- a/sdks/csharp/tests/SnapshotTests.cs +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -26,11 +26,6 @@ public void Log(string message) public void LogWarning(string message) { - // We don't start tracking in test simulation, so those warnings are expected. - if (message.StartsWith("Failed to finish tracking")) - { - return; - } events.Add("LogWarning", message); } @@ -95,18 +90,40 @@ private static string GetTestDir([CallerFilePath] string testFilePath = "") => [Fact] public async Task VerifyAllTablesParsed() { - var settings = new JsonSerializerSettings + var events = new Events(); + + Logger.Current = new TestLogger(events); + + var client = SpacetimeDBClient.instance; + + var jsonSettings = new JsonSerializerSettings { Converters = [new ByteStringReaderConverter()] }; // We store the dump in JSON-NL format for simplicity (it's just `ClientApi.Message.toString()`) and readability. var sampleDumpParsed = File.ReadLines(Path.Combine(GetTestDir(), "sample-dump.jsonl")) - .Select(line => JsonConvert.DeserializeObject(line, settings)); + .Select(line => JsonConvert.DeserializeObject(line, jsonSettings)); // But for proper testing we need to convert it back to raw binary messages as if it was received over network. - var sampleDumpBinary = sampleDumpParsed.Select(message => + var sampleDumpBinary = sampleDumpParsed.Select((message, i) => { + // Start tracking requests in the stats handler so that those request IDs can later be found. + switch (message) + { + case { + TypeCase: ClientApi.Message.TypeOneofCase.SubscriptionUpdate, + SubscriptionUpdate: var subscriptionUpdate + }: + client.stats.SubscriptionRequestTracker.StartTrackingRequest($"sample#{i}"); + break; + case { + TypeCase: ClientApi.Message.TypeOneofCase.TransactionUpdate, + TransactionUpdate: var transactionUpdate + }: + client.stats.ReducerRequestTracker.StartTrackingRequest($"sample#{i}"); + break; + } using var output = new MemoryStream(); using (var brotli = new BrotliStream(output, CompressionMode.Compress)) { @@ -115,12 +132,6 @@ public async Task VerifyAllTablesParsed() return output.ToArray(); }); - var events = new Events(); - - Logger.Current = new TestLogger(events); - - var client = SpacetimeDBClient.instance; - Identity? myIdentity = null; client.onBeforeSubscriptionApplied += () => events.Add("OnBeforeSubscriptionApplied"); @@ -178,12 +189,17 @@ await Verify( { User = User.Iter().ToList(), Message = Message.Iter().ToList() - } + }, + Stats = client.stats } ) .AddExtraSettings(settings => settings.Converters.AddRange( - [new EventsConverter(), new IdentityConverter(myIdentity)] + [ + new EventsConverter(), + new IdentityConverter(myIdentity), + new NetworkRequestTrackerConverter() + ] ) ) .ScrubMember(_ => _.CallerIdentity); diff --git a/sdks/csharp/tests/VerifyInit.cs b/sdks/csharp/tests/VerifyInit.cs index 3410dd136ce..a88d76265e0 100644 --- a/sdks/csharp/tests/VerifyInit.cs +++ b/sdks/csharp/tests/VerifyInit.cs @@ -36,6 +36,34 @@ public override void Write(VerifyJsonWriter writer, Address value) } } +class NetworkRequestTrackerConverter : WriteOnlyJsonConverter +{ + public override void Write(VerifyJsonWriter writer, NetworkRequestTracker value) + { + writer.WriteStartObject(); + + var sampleCount = value.GetSampleCount(); + if (sampleCount > 0) + { + writer.WriteMember(value, sampleCount, nameof(sampleCount)); + } + + var requestsAwaitingResponse = value.GetRequestsAwaitingResponse(); + if (requestsAwaitingResponse > 0) + { + writer.WriteMember(value, requestsAwaitingResponse, nameof(requestsAwaitingResponse)); + } + + if (value.GetMinMaxTimes(int.MaxValue) is { Min.Metadata: var Min, Max.Metadata: var Max }) + { + writer.WriteMember(value, Min, nameof(Min)); + writer.WriteMember(value, Max, nameof(Max)); + } + + writer.WriteEndObject(); + } +} + static class VerifyInit { [ModuleInitializer] From e34545230499ce8196bc0f18a7cd6c9741759ab8 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 15 Jun 2024 23:43:06 +0100 Subject: [PATCH 090/223] Fix formatting --- sdks/csharp/tests/SnapshotTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs index 29b20a30379..b3e6f0cdd50 100644 --- a/sdks/csharp/tests/SnapshotTests.cs +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -111,13 +111,15 @@ public async Task VerifyAllTablesParsed() // Start tracking requests in the stats handler so that those request IDs can later be found. switch (message) { - case { + case + { TypeCase: ClientApi.Message.TypeOneofCase.SubscriptionUpdate, SubscriptionUpdate: var subscriptionUpdate }: client.stats.SubscriptionRequestTracker.StartTrackingRequest($"sample#{i}"); break; - case { + case + { TypeCase: ClientApi.Message.TypeOneofCase.TransactionUpdate, TransactionUpdate: var transactionUpdate }: From 9c01734a1e8e04aa7d15fceec8991c82187f35b0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 17 Jun 2024 11:48:04 +0100 Subject: [PATCH 091/223] Simplify Identity scrubbing --- ...otTests.VerifyAllTablesParsed.received.txt | 408 ++++++++++++++++++ sdks/csharp/tests/SnapshotTests.cs | 57 ++- sdks/csharp/tests/VerifyInit.cs | 19 +- 3 files changed, 443 insertions(+), 41 deletions(-) create mode 100644 sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.received.txt diff --git a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.received.txt b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.received.txt new file mode 100644 index 00000000000..34d30c98eaf --- /dev/null +++ b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.received.txt @@ -0,0 +1,408 @@ +{ + Events: { + OnIdentityReceived: { + identity: Identity_1, + address: Guid_1 + }, + OnInsertUser: { + user: { + identity: Identity_1, + online: true + } + }, + LogException: Unknown reducer __identity_connected__ (Parameter 'Reducer'), + OnInsertUser: { + user: { + identity: Identity_2, + online: true + } + }, + OnEvent: { + Timestamp: 1718487763059031, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: __identity_connected__, + ArgBytes: + }, + Message: , + EnergyQuantaUsed: 1957615, + HostExecutionDurationMicros: 66, + CallerAddress: Guid_2 + }, + OnUpdateUser: { + oldUser: { + identity: Identity_1, + online: true + }, + newUser: { + identity: Identity_1, + name: A, + online: true + }, + reducerEvent: { + Args: { + Name: A + }, + Timestamp: 1718487768057579, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718487768057579, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: set_name, + ArgBytes: 0100000041, + RequestId: 1, + CallInfo: { + Args: { + Name: A + }, + Timestamp: 1718487768057579, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 4345615, + HostExecutionDurationMicros: 70, + CallerAddress: Guid_1 + }, + OnSetName: { + Args: { + Name: A + }, + Timestamp: 1718487768057579, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + }, + OnInsertMessage: { + message: { + sender: Identity_2, + sent: 1718487775346381, + text: Hello, A! + }, + reducerEvent: { + Args: { + Text: Hello, A! + }, + Timestamp: 1718487775346381, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718487775346381, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: send_message, + ArgBytes: 0900000048656C6C6F2C204121, + RequestId: 1, + CallInfo: { + Args: { + Text: Hello, A! + }, + Timestamp: 1718487775346381, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2779615, + HostExecutionDurationMicros: 57, + CallerAddress: Guid_2 + }, + OnSendMessage: { + Args: { + Text: Hello, A! + }, + Timestamp: 1718487775346381, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + }, + OnUpdateUser: { + oldUser: { + identity: Identity_2, + online: true + }, + newUser: { + identity: Identity_2, + name: B, + online: true + }, + reducerEvent: { + Args: { + Name: B + }, + Timestamp: 1718487777307855, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718487777307855, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: set_name, + ArgBytes: 0100000042, + RequestId: 2, + CallInfo: { + Args: { + Name: B + }, + Timestamp: 1718487777307855, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 4268615, + HostExecutionDurationMicros: 98, + CallerAddress: Guid_2 + }, + OnSetName: { + Args: { + Name: B + }, + Timestamp: 1718487777307855, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + }, + OnInsertMessage: { + message: { + sender: Identity_1, + sent: 1718487783175083, + text: Hello, B! + }, + reducerEvent: { + Args: { + Text: Hello, B! + }, + Timestamp: 1718487783175083, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718487783175083, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: send_message, + ArgBytes: 0900000048656C6C6F2C204221, + RequestId: 2, + CallInfo: { + Args: { + Text: Hello, B! + }, + Timestamp: 1718487783175083, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2677615, + HostExecutionDurationMicros: 40, + CallerAddress: Guid_1 + }, + OnSendMessage: { + Args: { + Text: Hello, B! + }, + Timestamp: 1718487783175083, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + }, + OnInsertMessage: { + message: { + sender: Identity_2, + sent: 1718487787645364, + text: Goodbye! + }, + reducerEvent: { + Args: { + Text: Goodbye! + }, + Timestamp: 1718487787645364, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718487787645364, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: send_message, + ArgBytes: 08000000476F6F6462796521, + RequestId: 3, + CallInfo: { + Args: { + Text: Goodbye! + }, + Timestamp: 1718487787645364, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2636615, + HostExecutionDurationMicros: 28, + CallerAddress: Guid_2 + }, + OnSendMessage: { + Args: { + Text: Goodbye! + }, + Timestamp: 1718487787645364, + Identity: Identity_2, + CallerAddress: Guid_2, + ErrMessage: + }, + LogException: Unknown reducer __identity_disconnected__ (Parameter 'Reducer'), + OnUpdateUser: { + oldUser: { + identity: Identity_2, + name: B, + online: true + }, + newUser: { + identity: Identity_2, + name: B, + online: false + } + }, + OnEvent: { + Timestamp: 1718487791901504, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: __identity_disconnected__, + ArgBytes: + }, + Message: , + EnergyQuantaUsed: 3595615, + HostExecutionDurationMicros: 75, + CallerAddress: Guid_2 + }, + OnInsertMessage: { + message: { + sender: Identity_1, + sent: 1718487794937841, + text: Goodbye! + }, + reducerEvent: { + Args: { + Text: Goodbye! + }, + Timestamp: 1718487794937841, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + } + }, + OnEvent: { + Timestamp: 1718487794937841, + CallerIdentity: {Scrubbed}, + FunctionCall: { + Reducer: send_message, + ArgBytes: 08000000476F6F6462796521, + RequestId: 3, + CallInfo: { + Args: { + Text: Goodbye! + }, + Timestamp: 1718487794937841, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + } + }, + Message: , + EnergyQuantaUsed: 2636615, + HostExecutionDurationMicros: 34, + CallerAddress: Guid_1 + }, + OnSendMessage: { + Args: { + Text: Goodbye! + }, + Timestamp: 1718487794937841, + Identity: Identity_1, + CallerAddress: Guid_1, + ErrMessage: + } + }, + FinalSnapshot: { + User: [ + { + identity: Identity_1, + name: A, + online: true + }, + { + identity: Identity_2, + name: B, + online: false + } + ], + Message: [ + { + sender: Identity_2, + sent: 1718487775346381, + text: Hello, A! + }, + { + sender: Identity_1, + sent: 1718487783175083, + text: Hello, B! + }, + { + sender: Identity_2, + sent: 1718487787645364, + text: Goodbye! + }, + { + sender: Identity_1, + sent: 1718487794937841, + text: Goodbye! + } + ] + }, + Stats: { + ReducerRequestTracker: { + sampleCount: 3, + requestsAwaitingResponse: 5, + Min: sample#4, + Max: sample#2 + }, + OneOffRequestTracker: {}, + SubscriptionRequestTracker: { + sampleCount: 1, + Min: sample#1, + Max: sample#1 + }, + AllReducersTracker: { + sampleCount: 8, + Min: reducer=send_message, + Max: reducer=set_name + }, + ParseMessageTracker: { + sampleCount: 9, + Min: type=TransactionUpdate,reducer=send_message, + Max: type=SubscriptionUpdate + } + } +} \ No newline at end of file diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs index b3e6f0cdd50..10f3c534af9 100644 --- a/sdks/csharp/tests/SnapshotTests.cs +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -106,43 +106,38 @@ public async Task VerifyAllTablesParsed() .Select(line => JsonConvert.DeserializeObject(line, jsonSettings)); // But for proper testing we need to convert it back to raw binary messages as if it was received over network. - var sampleDumpBinary = sampleDumpParsed.Select((message, i) => - { - // Start tracking requests in the stats handler so that those request IDs can later be found. - switch (message) + var sampleDumpBinary = sampleDumpParsed.Select( + (message, i) => { - case + // Start tracking requests in the stats handler so that those request IDs can later be found. + switch (message) { - TypeCase: ClientApi.Message.TypeOneofCase.SubscriptionUpdate, - SubscriptionUpdate: var subscriptionUpdate - }: - client.stats.SubscriptionRequestTracker.StartTrackingRequest($"sample#{i}"); - break; - case + case { + TypeCase: ClientApi.Message.TypeOneofCase.SubscriptionUpdate, + SubscriptionUpdate: var subscriptionUpdate + }: + client.stats.SubscriptionRequestTracker.StartTrackingRequest($"sample#{i}"); + break; + case { + TypeCase: ClientApi.Message.TypeOneofCase.TransactionUpdate, + TransactionUpdate: var transactionUpdate + }: + client.stats.ReducerRequestTracker.StartTrackingRequest($"sample#{i}"); + break; + } + using var output = new MemoryStream(); + using (var brotli = new BrotliStream(output, CompressionMode.Compress)) { - TypeCase: ClientApi.Message.TypeOneofCase.TransactionUpdate, - TransactionUpdate: var transactionUpdate - }: - client.stats.ReducerRequestTracker.StartTrackingRequest($"sample#{i}"); - break; - } - using var output = new MemoryStream(); - using (var brotli = new BrotliStream(output, CompressionMode.Compress)) - { - message.WriteTo(brotli); + message.WriteTo(brotli); + } + return output.ToArray(); } - return output.ToArray(); - }); - - Identity? myIdentity = null; + ); client.onBeforeSubscriptionApplied += () => events.Add("OnBeforeSubscriptionApplied"); client.onEvent += (ev) => events.Add("OnEvent", ev); client.onIdentityReceived += (_authToken, identity, address) => - { - myIdentity = identity; events.Add("OnIdentityReceived", new { identity, address }); - }; client.onSubscriptionApplied += () => events.Add("OnSubscriptionApplied"); client.onUnhandledReducerError += (exception) => events.Add("OnUnhandledReducerError", exception); @@ -197,11 +192,7 @@ await Verify( ) .AddExtraSettings(settings => settings.Converters.AddRange( - [ - new EventsConverter(), - new IdentityConverter(myIdentity), - new NetworkRequestTrackerConverter() - ] + [new EventsConverter(), new NetworkRequestTrackerConverter()] ) ) .ScrubMember(_ => _.CallerIdentity); diff --git a/sdks/csharp/tests/VerifyInit.cs b/sdks/csharp/tests/VerifyInit.cs index a88d76265e0..9815b3f53f4 100644 --- a/sdks/csharp/tests/VerifyInit.cs +++ b/sdks/csharp/tests/VerifyInit.cs @@ -13,18 +13,20 @@ public override void Write(VerifyJsonWriter writer, ByteString value) } // A converter that scrubs identity to a stable string. -public class IdentityConverter(Identity? myIdentity) : WriteOnlyJsonConverter +class IdentityConverter : WriteOnlyJsonConverter { + private static readonly List seenIdentities = []; + public override void Write(VerifyJsonWriter writer, Identity value) { - if (value == myIdentity) - { - writer.WriteValue("(identity of A)"); - } - else + var index = seenIdentities.IndexOf(value); + if (index == -1) { - writer.WriteValue("(identity of B)"); + index = seenIdentities.Count; + seenIdentities.Add(value); } + + writer.WriteValue($"Identity_{index + 1}"); } } @@ -32,6 +34,7 @@ class AddressConverter : WriteOnlyJsonConverter
    { public override void Write(VerifyJsonWriter writer, Address value) { + // Addresses are GUIDs, which Verify scrubs automatically. writer.WriteValue(value.ToString()); } } @@ -73,7 +76,7 @@ public static void Init() VerifierSettings.AddExtraSettings(settings => settings.Converters.AddRange( - [new ByteStringConverter(), new AddressConverter()] + [new ByteStringConverter(), new IdentityConverter(), new AddressConverter()] ) ); From 27120e824257ab9132e90a7e86ba116518d29c83 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 17 Jun 2024 11:50:42 +0100 Subject: [PATCH 092/223] Move Verify converters around --- sdks/csharp/tests/SnapshotTests.cs | 38 +++++------ sdks/csharp/tests/VerifyInit.cs | 106 ++++++++++++++++------------- 2 files changed, 77 insertions(+), 67 deletions(-) diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs index 10f3c534af9..c6eb2af4097 100644 --- a/sdks/csharp/tests/SnapshotTests.cs +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -17,6 +17,19 @@ public void Add(string name, object? value = null) } } + class EventsConverter : WriteOnlyJsonConverter + { + public override void Write(VerifyJsonWriter writer, Events events) + { + writer.WriteStartObject(); + foreach (var (name, value) in events) + { + writer.WriteMember(events, value, name); + } + writer.WriteEndObject(); + } + } + class TestLogger(Events events) : ISpacetimeDBLogger { public void Log(string message) @@ -40,19 +53,6 @@ public void LogException(Exception e) } } - class EventsConverter : WriteOnlyJsonConverter - { - public override void Write(VerifyJsonWriter writer, Events events) - { - writer.WriteStartObject(); - foreach (var (name, value) in events) - { - writer.WriteMember(events, value, name); - } - writer.WriteEndObject(); - } - } - class ByteStringReaderConverter : JsonConverter { public override ByteString ReadJson( @@ -112,13 +112,15 @@ public async Task VerifyAllTablesParsed() // Start tracking requests in the stats handler so that those request IDs can later be found. switch (message) { - case { + case + { TypeCase: ClientApi.Message.TypeOneofCase.SubscriptionUpdate, SubscriptionUpdate: var subscriptionUpdate }: client.stats.SubscriptionRequestTracker.StartTrackingRequest($"sample#{i}"); break; - case { + case + { TypeCase: ClientApi.Message.TypeOneofCase.TransactionUpdate, TransactionUpdate: var transactionUpdate }: @@ -190,11 +192,7 @@ await Verify( Stats = client.stats } ) - .AddExtraSettings(settings => - settings.Converters.AddRange( - [new EventsConverter(), new NetworkRequestTrackerConverter()] - ) - ) + .AddExtraSettings(settings => settings.Converters.AddRange([new EventsConverter()])) .ScrubMember(_ => _.CallerIdentity); } } diff --git a/sdks/csharp/tests/VerifyInit.cs b/sdks/csharp/tests/VerifyInit.cs index 9815b3f53f4..985045537a2 100644 --- a/sdks/csharp/tests/VerifyInit.cs +++ b/sdks/csharp/tests/VerifyInit.cs @@ -4,71 +4,78 @@ namespace SpacetimeDB.Tests; using Google.Protobuf; using SpacetimeDB.Types; -class ByteStringConverter : WriteOnlyJsonConverter +static class VerifyInit { - public override void Write(VerifyJsonWriter writer, ByteString value) + class ByteStringConverter : WriteOnlyJsonConverter { - writer.WriteValue(Convert.ToHexString(value.Span)); + public override void Write(VerifyJsonWriter writer, ByteString value) + { + writer.WriteValue(Convert.ToHexString(value.Span)); + } } -} -// A converter that scrubs identity to a stable string. -class IdentityConverter : WriteOnlyJsonConverter -{ - private static readonly List seenIdentities = []; - - public override void Write(VerifyJsonWriter writer, Identity value) + // A converter that scrubs identity to a stable string. + class IdentityConverter : WriteOnlyJsonConverter { - var index = seenIdentities.IndexOf(value); - if (index == -1) + private static readonly List seenIdentities = []; + + public override void Write(VerifyJsonWriter writer, Identity value) { - index = seenIdentities.Count; - seenIdentities.Add(value); - } + var index = seenIdentities.IndexOf(value); + if (index == -1) + { + index = seenIdentities.Count; + seenIdentities.Add(value); + } - writer.WriteValue($"Identity_{index + 1}"); + writer.WriteValue($"Identity_{index + 1}"); + } } -} -class AddressConverter : WriteOnlyJsonConverter
    -{ - public override void Write(VerifyJsonWriter writer, Address value) + class AddressConverter : WriteOnlyJsonConverter
    { - // Addresses are GUIDs, which Verify scrubs automatically. - writer.WriteValue(value.ToString()); + public override void Write(VerifyJsonWriter writer, Address value) + { + // Addresses are GUIDs, which Verify scrubs automatically. + writer.WriteValue(value.ToString()); + } } -} -class NetworkRequestTrackerConverter : WriteOnlyJsonConverter -{ - public override void Write(VerifyJsonWriter writer, NetworkRequestTracker value) + class NetworkRequestTrackerConverter : WriteOnlyJsonConverter { - writer.WriteStartObject(); - - var sampleCount = value.GetSampleCount(); - if (sampleCount > 0) + public override void Write(VerifyJsonWriter writer, NetworkRequestTracker value) { - writer.WriteMember(value, sampleCount, nameof(sampleCount)); - } + writer.WriteStartObject(); - var requestsAwaitingResponse = value.GetRequestsAwaitingResponse(); - if (requestsAwaitingResponse > 0) - { - writer.WriteMember(value, requestsAwaitingResponse, nameof(requestsAwaitingResponse)); - } + var sampleCount = value.GetSampleCount(); + if (sampleCount > 0) + { + writer.WriteMember(value, sampleCount, nameof(sampleCount)); + } - if (value.GetMinMaxTimes(int.MaxValue) is { Min.Metadata: var Min, Max.Metadata: var Max }) - { - writer.WriteMember(value, Min, nameof(Min)); - writer.WriteMember(value, Max, nameof(Max)); - } + var requestsAwaitingResponse = value.GetRequestsAwaitingResponse(); + if (requestsAwaitingResponse > 0) + { + writer.WriteMember( + value, + requestsAwaitingResponse, + nameof(requestsAwaitingResponse) + ); + } - writer.WriteEndObject(); + if ( + value.GetMinMaxTimes(int.MaxValue) is + { Min.Metadata: var Min, Max.Metadata: var Max } + ) + { + writer.WriteMember(value, Min, nameof(Min)); + writer.WriteMember(value, Max, nameof(Max)); + } + + writer.WriteEndObject(); + } } -} -static class VerifyInit -{ [ModuleInitializer] public static void Init() { @@ -76,7 +83,12 @@ public static void Init() VerifierSettings.AddExtraSettings(settings => settings.Converters.AddRange( - [new ByteStringConverter(), new IdentityConverter(), new AddressConverter()] + [ + new ByteStringConverter(), + new IdentityConverter(), + new AddressConverter(), + new NetworkRequestTrackerConverter() + ] ) ); From 7e8a6ed87636c519d023c46fcd5eb190c5ab24ef Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 17 Jun 2024 21:05:18 +0100 Subject: [PATCH 093/223] Update test snapshots --- ...otTests.VerifyAllTablesParsed.received.txt | 408 ------------------ ...otTests.VerifyAllTablesParsed.verified.txt | 74 ++-- 2 files changed, 37 insertions(+), 445 deletions(-) delete mode 100644 sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.received.txt diff --git a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.received.txt b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.received.txt deleted file mode 100644 index 34d30c98eaf..00000000000 --- a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.received.txt +++ /dev/null @@ -1,408 +0,0 @@ -{ - Events: { - OnIdentityReceived: { - identity: Identity_1, - address: Guid_1 - }, - OnInsertUser: { - user: { - identity: Identity_1, - online: true - } - }, - LogException: Unknown reducer __identity_connected__ (Parameter 'Reducer'), - OnInsertUser: { - user: { - identity: Identity_2, - online: true - } - }, - OnEvent: { - Timestamp: 1718487763059031, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: __identity_connected__, - ArgBytes: - }, - Message: , - EnergyQuantaUsed: 1957615, - HostExecutionDurationMicros: 66, - CallerAddress: Guid_2 - }, - OnUpdateUser: { - oldUser: { - identity: Identity_1, - online: true - }, - newUser: { - identity: Identity_1, - name: A, - online: true - }, - reducerEvent: { - Args: { - Name: A - }, - Timestamp: 1718487768057579, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } - }, - OnEvent: { - Timestamp: 1718487768057579, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: set_name, - ArgBytes: 0100000041, - RequestId: 1, - CallInfo: { - Args: { - Name: A - }, - Timestamp: 1718487768057579, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 4345615, - HostExecutionDurationMicros: 70, - CallerAddress: Guid_1 - }, - OnSetName: { - Args: { - Name: A - }, - Timestamp: 1718487768057579, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - }, - OnInsertMessage: { - message: { - sender: Identity_2, - sent: 1718487775346381, - text: Hello, A! - }, - reducerEvent: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718487775346381, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } - }, - OnEvent: { - Timestamp: 1718487775346381, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: send_message, - ArgBytes: 0900000048656C6C6F2C204121, - RequestId: 1, - CallInfo: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718487775346381, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 2779615, - HostExecutionDurationMicros: 57, - CallerAddress: Guid_2 - }, - OnSendMessage: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718487775346381, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - }, - OnUpdateUser: { - oldUser: { - identity: Identity_2, - online: true - }, - newUser: { - identity: Identity_2, - name: B, - online: true - }, - reducerEvent: { - Args: { - Name: B - }, - Timestamp: 1718487777307855, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } - }, - OnEvent: { - Timestamp: 1718487777307855, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: set_name, - ArgBytes: 0100000042, - RequestId: 2, - CallInfo: { - Args: { - Name: B - }, - Timestamp: 1718487777307855, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 4268615, - HostExecutionDurationMicros: 98, - CallerAddress: Guid_2 - }, - OnSetName: { - Args: { - Name: B - }, - Timestamp: 1718487777307855, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - }, - OnInsertMessage: { - message: { - sender: Identity_1, - sent: 1718487783175083, - text: Hello, B! - }, - reducerEvent: { - Args: { - Text: Hello, B! - }, - Timestamp: 1718487783175083, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } - }, - OnEvent: { - Timestamp: 1718487783175083, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: send_message, - ArgBytes: 0900000048656C6C6F2C204221, - RequestId: 2, - CallInfo: { - Args: { - Text: Hello, B! - }, - Timestamp: 1718487783175083, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 2677615, - HostExecutionDurationMicros: 40, - CallerAddress: Guid_1 - }, - OnSendMessage: { - Args: { - Text: Hello, B! - }, - Timestamp: 1718487783175083, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - }, - OnInsertMessage: { - message: { - sender: Identity_2, - sent: 1718487787645364, - text: Goodbye! - }, - reducerEvent: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487787645364, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } - }, - OnEvent: { - Timestamp: 1718487787645364, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: send_message, - ArgBytes: 08000000476F6F6462796521, - RequestId: 3, - CallInfo: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487787645364, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 2636615, - HostExecutionDurationMicros: 28, - CallerAddress: Guid_2 - }, - OnSendMessage: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487787645364, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - }, - LogException: Unknown reducer __identity_disconnected__ (Parameter 'Reducer'), - OnUpdateUser: { - oldUser: { - identity: Identity_2, - name: B, - online: true - }, - newUser: { - identity: Identity_2, - name: B, - online: false - } - }, - OnEvent: { - Timestamp: 1718487791901504, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: __identity_disconnected__, - ArgBytes: - }, - Message: , - EnergyQuantaUsed: 3595615, - HostExecutionDurationMicros: 75, - CallerAddress: Guid_2 - }, - OnInsertMessage: { - message: { - sender: Identity_1, - sent: 1718487794937841, - text: Goodbye! - }, - reducerEvent: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487794937841, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } - }, - OnEvent: { - Timestamp: 1718487794937841, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: send_message, - ArgBytes: 08000000476F6F6462796521, - RequestId: 3, - CallInfo: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487794937841, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } - }, - Message: , - EnergyQuantaUsed: 2636615, - HostExecutionDurationMicros: 34, - CallerAddress: Guid_1 - }, - OnSendMessage: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487794937841, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } - }, - FinalSnapshot: { - User: [ - { - identity: Identity_1, - name: A, - online: true - }, - { - identity: Identity_2, - name: B, - online: false - } - ], - Message: [ - { - sender: Identity_2, - sent: 1718487775346381, - text: Hello, A! - }, - { - sender: Identity_1, - sent: 1718487783175083, - text: Hello, B! - }, - { - sender: Identity_2, - sent: 1718487787645364, - text: Goodbye! - }, - { - sender: Identity_1, - sent: 1718487794937841, - text: Goodbye! - } - ] - }, - Stats: { - ReducerRequestTracker: { - sampleCount: 3, - requestsAwaitingResponse: 5, - Min: sample#4, - Max: sample#2 - }, - OneOffRequestTracker: {}, - SubscriptionRequestTracker: { - sampleCount: 1, - Min: sample#1, - Max: sample#1 - }, - AllReducersTracker: { - sampleCount: 8, - Min: reducer=send_message, - Max: reducer=set_name - }, - ParseMessageTracker: { - sampleCount: 9, - Min: type=TransactionUpdate,reducer=send_message, - Max: type=SubscriptionUpdate - } - } -} \ No newline at end of file diff --git a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt index fdcf9eb110a..34d30c98eaf 100644 --- a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -1,19 +1,19 @@ { Events: { OnIdentityReceived: { - identity: (identity of A), + identity: Identity_1, address: Guid_1 }, OnInsertUser: { user: { - identity: (identity of A), + identity: Identity_1, online: true } }, LogException: Unknown reducer __identity_connected__ (Parameter 'Reducer'), OnInsertUser: { user: { - identity: (identity of B), + identity: Identity_2, online: true } }, @@ -31,11 +31,11 @@ }, OnUpdateUser: { oldUser: { - identity: (identity of A), + identity: Identity_1, online: true }, newUser: { - identity: (identity of A), + identity: Identity_1, name: A, online: true }, @@ -44,7 +44,7 @@ Name: A }, Timestamp: 1718487768057579, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: } @@ -61,7 +61,7 @@ Name: A }, Timestamp: 1718487768057579, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: } @@ -76,13 +76,13 @@ Name: A }, Timestamp: 1718487768057579, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: }, OnInsertMessage: { message: { - sender: (identity of B), + sender: Identity_2, sent: 1718487775346381, text: Hello, A! }, @@ -91,7 +91,7 @@ Text: Hello, A! }, Timestamp: 1718487775346381, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: } @@ -108,7 +108,7 @@ Text: Hello, A! }, Timestamp: 1718487775346381, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: } @@ -123,17 +123,17 @@ Text: Hello, A! }, Timestamp: 1718487775346381, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: }, OnUpdateUser: { oldUser: { - identity: (identity of B), + identity: Identity_2, online: true }, newUser: { - identity: (identity of B), + identity: Identity_2, name: B, online: true }, @@ -142,7 +142,7 @@ Name: B }, Timestamp: 1718487777307855, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: } @@ -159,7 +159,7 @@ Name: B }, Timestamp: 1718487777307855, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: } @@ -174,13 +174,13 @@ Name: B }, Timestamp: 1718487777307855, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: }, OnInsertMessage: { message: { - sender: (identity of A), + sender: Identity_1, sent: 1718487783175083, text: Hello, B! }, @@ -189,7 +189,7 @@ Text: Hello, B! }, Timestamp: 1718487783175083, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: } @@ -206,7 +206,7 @@ Text: Hello, B! }, Timestamp: 1718487783175083, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: } @@ -221,13 +221,13 @@ Text: Hello, B! }, Timestamp: 1718487783175083, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: }, OnInsertMessage: { message: { - sender: (identity of B), + sender: Identity_2, sent: 1718487787645364, text: Goodbye! }, @@ -236,7 +236,7 @@ Text: Goodbye! }, Timestamp: 1718487787645364, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: } @@ -253,7 +253,7 @@ Text: Goodbye! }, Timestamp: 1718487787645364, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: } @@ -268,19 +268,19 @@ Text: Goodbye! }, Timestamp: 1718487787645364, - Identity: (identity of B), + Identity: Identity_2, CallerAddress: Guid_2, ErrMessage: }, LogException: Unknown reducer __identity_disconnected__ (Parameter 'Reducer'), OnUpdateUser: { oldUser: { - identity: (identity of B), + identity: Identity_2, name: B, online: true }, newUser: { - identity: (identity of B), + identity: Identity_2, name: B, online: false } @@ -299,7 +299,7 @@ }, OnInsertMessage: { message: { - sender: (identity of A), + sender: Identity_1, sent: 1718487794937841, text: Goodbye! }, @@ -308,7 +308,7 @@ Text: Goodbye! }, Timestamp: 1718487794937841, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: } @@ -325,7 +325,7 @@ Text: Goodbye! }, Timestamp: 1718487794937841, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: } @@ -340,7 +340,7 @@ Text: Goodbye! }, Timestamp: 1718487794937841, - Identity: (identity of A), + Identity: Identity_1, CallerAddress: Guid_1, ErrMessage: } @@ -348,34 +348,34 @@ FinalSnapshot: { User: [ { - identity: (identity of A), + identity: Identity_1, name: A, online: true }, { - identity: (identity of B), + identity: Identity_2, name: B, online: false } ], Message: [ { - sender: (identity of B), + sender: Identity_2, sent: 1718487775346381, text: Hello, A! }, { - sender: (identity of A), + sender: Identity_1, sent: 1718487783175083, text: Hello, B! }, { - sender: (identity of B), + sender: Identity_2, sent: 1718487787645364, text: Goodbye! }, { - sender: (identity of A), + sender: Identity_1, sent: 1718487794937841, text: Goodbye! } From 06285d3c0633f4a37661b134ac92ece1afc6dc2a Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Thu, 11 Jul 2024 13:40:32 -0400 Subject: [PATCH 094/223] Protobufectomy: c# sdk (#104) ## Description of Changes - Removed JSON support (similar to changes being made on the TypeScript side) - Removed all references to protobuf - Swapped the protobuf codegen for the output of our own C# codegen in rust - Refactored the connection class to reflect the API changes from protobuf to bsatn - Updated the example to reflect these changes ## API - [ ] This is an API breaking change to the SDK Changes the SDK types passed into event handlers. ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 2 +- .../examples/quickstart/client/Program.cs | 5 +- .../_Globals/SpacetimeDBClient.cs | 15 +- sdks/csharp/src/BSATNHelpers.cs | 55 +- sdks/csharp/src/ClientApi.cs | 3824 ----------------- sdks/csharp/src/ClientApiExtensions.cs | 7 - sdks/csharp/src/ClientCache.cs | 6 +- sdks/csharp/src/IDatabaseTable.cs | 27 +- sdks/csharp/src/Primitives.cs | 83 + .../src/SpacetimeDB/ClientApi/CallReducer.cs | 28 + .../SpacetimeDB/ClientApi/ClientMessage.cs | 17 + .../SpacetimeDB/ClientApi/DatabaseUpdate.cs | 22 + .../src/SpacetimeDB/ClientApi/EncodedValue.cs | 17 + .../src/SpacetimeDB/ClientApi/EnergyQuanta.cs | 22 + .../SpacetimeDB/ClientApi/IdentityToken.cs | 28 + .../ClientApi/InitialSubscription.cs | 28 + .../src/SpacetimeDB/ClientApi/OneOffQuery.cs | 25 + .../ClientApi/OneOffQueryResponse.cs | 31 + .../src/SpacetimeDB/ClientApi/OneOffTable.cs | 25 + .../SpacetimeDB/ClientApi/ReducerCallInfo.cs | 31 + .../SpacetimeDB/ClientApi/ServerMessage.cs | 18 + .../src/SpacetimeDB/ClientApi/Subscribe.cs | 25 + .../src/SpacetimeDB/ClientApi/TableUpdate.cs | 31 + .../src/SpacetimeDB/ClientApi/Timestamp.cs | 23 + .../ClientApi/TransactionUpdate.cs | 40 + .../src/SpacetimeDB/ClientApi/UpdateStatus.cs | 18 + sdks/csharp/src/SpacetimeDBClient.cs | 349 +- sdks/csharp/src/Stubs.cs | 28 +- sdks/csharp/src/Utils.cs | 4 +- sdks/csharp/src/WebSocket.cs | 17 +- ...otTests.VerifyAllTablesParsed.verified.txt | 236 +- sdks/csharp/tests/SnapshotTests.cs | 256 +- sdks/csharp/tests/VerifyInit.cs | 10 - sdks/csharp/tests/sample-dump.jsonl | 10 - 34 files changed, 1076 insertions(+), 4287 deletions(-) delete mode 100644 sdks/csharp/src/ClientApi.cs delete mode 100644 sdks/csharp/src/ClientApiExtensions.cs create mode 100644 sdks/csharp/src/Primitives.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs delete mode 100644 sdks/csharp/tests/sample-dump.jsonl diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index a6c750c1f40..51d95cd33b5 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -23,7 +23,7 @@ - + diff --git a/sdks/csharp/examples/quickstart/client/Program.cs b/sdks/csharp/examples/quickstart/client/Program.cs index 89b9329eb2f..056d940e83b 100644 --- a/sdks/csharp/examples/quickstart/client/Program.cs +++ b/sdks/csharp/examples/quickstart/client/Program.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading; using SpacetimeDB; +using SpacetimeDB.ClientApi; using SpacetimeDB.Types; // our local client SpacetimeDB identity @@ -97,7 +98,7 @@ void Message_OnInsert(Message insertedValue, ReducerEvent? dbEvent) void Reducer_OnSetNameEvent(ReducerEvent reducerEvent, string name) { - if (reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) + if (reducerEvent.Identity == local_identity && reducerEvent.Status is UpdateStatus.Failed) { Console.Write($"Failed to change name to {name}"); } @@ -105,7 +106,7 @@ void Reducer_OnSetNameEvent(ReducerEvent reducerEvent, string name) void Reducer_OnSendMessageEvent(ReducerEvent reducerEvent, string text) { - if (reducerEvent.Identity == local_identity && reducerEvent.Status == ClientApi.Event.Types.Status.Failed) + if (reducerEvent.Identity == local_identity && reducerEvent.Status is UpdateStatus.Failed) { Console.Write($"Failed to send message {text}"); } diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs index 5748f597d9c..49dae53e43a 100644 --- a/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs +++ b/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs @@ -6,6 +6,7 @@ using System; using SpacetimeDB; +using SpacetimeDB.ClientApi; namespace SpacetimeDB.Types { @@ -32,7 +33,7 @@ public partial class ReducerEvent : ReducerEventBase public ReducerType Reducer => Args?.ReducerType ?? ReducerType.None; public ReducerEvent(IReducerArgs? args) : base() => Args = args; - public ReducerEvent(ClientApi.Event dbEvent, IReducerArgs? args) : base(dbEvent) => Args = args; + public ReducerEvent(TransactionUpdate dbEvent, IReducerArgs? args) : base(dbEvent) => Args = args; [Obsolete("Accessors that implicitly cast `Args` are deprecated, please match `Args` against the desired type explicitly instead.")] public SendMessageArgsStruct SendMessageArgs => (SendMessageArgsStruct)Args!; @@ -52,16 +53,16 @@ protected SpacetimeDBClient() public static readonly SpacetimeDBClient instance = new(); - protected override ReducerEvent ReducerEventFromDbEvent(ClientApi.Event dbEvent) + protected override ReducerEvent ReducerEventFromDbEvent(TransactionUpdate update) { - var argBytes = dbEvent.FunctionCall.ArgBytes; - IReducerArgs? args = dbEvent.FunctionCall.Reducer switch { - "send_message" => BSATNHelpers.FromProtoBytes(argBytes), - "set_name" => BSATNHelpers.FromProtoBytes(argBytes), + var argBytes = update.ReducerCall.Args; + IReducerArgs? args = update.ReducerCall.ReducerName switch { + "send_message" => BSATNHelpers.Decode(argBytes), + "set_name" => BSATNHelpers.Decode(argBytes), "" => null, var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; - return new ReducerEvent(dbEvent, args); + return new ReducerEvent(update, args); } } } diff --git a/sdks/csharp/src/BSATNHelpers.cs b/sdks/csharp/src/BSATNHelpers.cs index 3ea5f79aac5..31f156284ec 100644 --- a/sdks/csharp/src/BSATNHelpers.cs +++ b/sdks/csharp/src/BSATNHelpers.cs @@ -1,7 +1,7 @@ using System; -using Google.Protobuf; using SpacetimeDB.BSATN; using System.IO; +using SpacetimeDB.ClientApi; namespace SpacetimeDB { @@ -14,56 +14,23 @@ public static T FromStream(Stream stream) return IStructuralReadWrite.Read(reader); } - // There is CommunityToolkit.HighPerformance that provides this, - // but it's not compatible with Unity as it relies on .NET intrinsics, - // so we need to implement our own. - class ProtoStream : Stream + public static T Decode(byte[] bsatn) where T : IStructuralReadWrite, new() { - private readonly ReadOnlyMemory memory; - - public ProtoStream(ByteString input) - { - memory = input.Memory; - } - - public override long Position { get; set; } - public override long Length => memory.Length; - - public override bool CanRead => true; - public override int Read(byte[] buffer, int offset, int count) - { - memory.Slice((int)Position, count).CopyTo(buffer.AsMemory(offset)); - Position += count; - return count; - } - - // Easy to implement, but not needed for our use cases. - public override bool CanSeek => false; - public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); - - - // Our stream is read-only. - public override bool CanWrite => false; - public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); - public override void Flush() { } - public override void SetLength(long value) => throw new NotSupportedException(); + using var stream = new MemoryStream(bsatn); + return FromStream(stream); } - public static T FromProtoBytes(ByteString bytes) + public static T Decode(string json) where T : IStructuralReadWrite, new() { - using var stream = new ProtoStream(bytes); - return FromStream(stream); + throw new InvalidOperationException("JSON isn't supported at the moment"); } - public static ByteString ToProtoBytes(this T value) - where T : IStructuralReadWrite, new() + public static T Decode(EncodedValue value) where T : IStructuralReadWrite, new() => value switch { - using var stream = new MemoryStream(); - using var writer = new BinaryWriter(stream); - value.WriteFields(writer); - // This is safe because we know we own args so nobody else will modify it. - return UnsafeByteOperations.UnsafeWrap(stream.ToArray()); - } + EncodedValue.Binary(var bin) => Decode(bin), + EncodedValue.Text(var text) => Decode(text), + _ => throw new InvalidOperationException() + }; } } diff --git a/sdks/csharp/src/ClientApi.cs b/sdks/csharp/src/ClientApi.cs deleted file mode 100644 index 6b382b93e90..00000000000 --- a/sdks/csharp/src/ClientApi.cs +++ /dev/null @@ -1,3824 +0,0 @@ -// -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: client_api.proto -// -#pragma warning disable 1591, 0612, 3021, 8981 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace ClientApi { - - /// Holder for reflection information generated from client_api.proto - public static partial class ClientApiReflection { - - #region Descriptor - /// File descriptor for client_api.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static ClientApiReflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "ChBjbGllbnRfYXBpLnByb3RvEgpjbGllbnRfYXBpIrEDCgdNZXNzYWdlEjAK", - "DGZ1bmN0aW9uQ2FsbBgBIAEoCzIYLmNsaWVudF9hcGkuRnVuY3Rpb25DYWxs", - "SAASPAoSc3Vic2NyaXB0aW9uVXBkYXRlGAIgASgLMh4uY2xpZW50X2FwaS5T", - "dWJzY3JpcHRpb25VcGRhdGVIABIiCgVldmVudBgDIAEoCzIRLmNsaWVudF9h", - "cGkuRXZlbnRIABI6ChF0cmFuc2FjdGlvblVwZGF0ZRgEIAEoCzIdLmNsaWVu", - "dF9hcGkuVHJhbnNhY3Rpb25VcGRhdGVIABIyCg1pZGVudGl0eVRva2VuGAUg", - "ASgLMhkuY2xpZW50X2FwaS5JZGVudGl0eVRva2VuSAASKgoJc3Vic2NyaWJl", - "GAYgASgLMhUuY2xpZW50X2FwaS5TdWJzY3JpYmVIABIuCgtvbmVPZmZRdWVy", - "eRgHIAEoCzIXLmNsaWVudF9hcGkuT25lT2ZmUXVlcnlIABI+ChNvbmVPZmZR", - "dWVyeVJlc3BvbnNlGAggASgLMh8uY2xpZW50X2FwaS5PbmVPZmZRdWVyeVJl", - "c3BvbnNlSABCBgoEdHlwZSJBCg1JZGVudGl0eVRva2VuEhAKCGlkZW50aXR5", - "GAEgASgMEg0KBXRva2VuGAIgASgJEg8KB2FkZHJlc3MYAyABKAwiRAoMRnVu", - "Y3Rpb25DYWxsEg8KB3JlZHVjZXIYASABKAkSEAoIYXJnQnl0ZXMYAiABKAwS", - "EQoJcmVxdWVzdElkGAMgASgNIjUKCVN1YnNjcmliZRIVCg1xdWVyeV9zdHJp", - "bmdzGAEgAygJEhEKCXJlcXVlc3RJZBgCIAEoDSKwAgoFRXZlbnQSEQoJdGlt", - "ZXN0YW1wGAEgASgEEhYKDmNhbGxlcklkZW50aXR5GAIgASgMEi4KDGZ1bmN0", - "aW9uQ2FsbBgDIAEoCzIYLmNsaWVudF9hcGkuRnVuY3Rpb25DYWxsEigKBnN0", - "YXR1cxgEIAEoDjIYLmNsaWVudF9hcGkuRXZlbnQuU3RhdHVzEg8KB21lc3Nh", - "Z2UYBSABKAkSGgoSZW5lcmd5X3F1YW50YV91c2VkGAYgASgDEiYKHmhvc3Rf", - "ZXhlY3V0aW9uX2R1cmF0aW9uX21pY3JvcxgHIAEoBBIVCg1jYWxsZXJBZGRy", - "ZXNzGAggASgMIjYKBlN0YXR1cxINCgljb21taXR0ZWQQABIKCgZmYWlsZWQQ", - "ARIRCg1vdXRfb2ZfZW5lcmd5EAIihAEKElN1YnNjcmlwdGlvblVwZGF0ZRIt", - "Cgx0YWJsZVVwZGF0ZXMYASADKAsyFy5jbGllbnRfYXBpLlRhYmxlVXBkYXRl", - "EhEKCXJlcXVlc3RJZBgCIAEoDRIsCiR0b3RhbF9ob3N0X2V4ZWN1dGlvbl9k", - "dXJhdGlvbl9taWNyb3MYAyABKAQibAoLVGFibGVVcGRhdGUSDwoHdGFibGVJ", - "ZBgBIAEoDRIRCgl0YWJsZU5hbWUYAiABKAkSOQoSdGFibGVSb3dPcGVyYXRp", - "b25zGAMgAygLMh0uY2xpZW50X2FwaS5UYWJsZVJvd09wZXJhdGlvbiKCAQoR", - "VGFibGVSb3dPcGVyYXRpb24SNwoCb3AYASABKA4yKy5jbGllbnRfYXBpLlRh", - "YmxlUm93T3BlcmF0aW9uLk9wZXJhdGlvblR5cGUSCwoDcm93GAMgASgMIicK", - "DU9wZXJhdGlvblR5cGUSCgoGREVMRVRFEAASCgoGSU5TRVJUEAEicQoRVHJh", - "bnNhY3Rpb25VcGRhdGUSIAoFZXZlbnQYASABKAsyES5jbGllbnRfYXBpLkV2", - "ZW50EjoKEnN1YnNjcmlwdGlvblVwZGF0ZRgCIAEoCzIeLmNsaWVudF9hcGku", - "U3Vic2NyaXB0aW9uVXBkYXRlIjUKC09uZU9mZlF1ZXJ5EhEKCW1lc3NhZ2VJ", - "ZBgBIAEoDBITCgtxdWVyeVN0cmluZxgCIAEoCSKOAQoTT25lT2ZmUXVlcnlS", - "ZXNwb25zZRIRCgltZXNzYWdlSWQYASABKAwSDQoFZXJyb3IYAiABKAkSJwoG", - "dGFibGVzGAMgAygLMhcuY2xpZW50X2FwaS5PbmVPZmZUYWJsZRIsCiR0b3Rh", - "bF9ob3N0X2V4ZWN1dGlvbl9kdXJhdGlvbl9taWNyb3MYBCABKAQiLQoLT25l", - "T2ZmVGFibGUSEQoJdGFibGVOYW1lGAIgASgJEgsKA3JvdxgEIAMoDGIGcHJv", - "dG8z")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Message), global::ClientApi.Message.Parser, new[]{ "FunctionCall", "SubscriptionUpdate", "Event", "TransactionUpdate", "IdentityToken", "Subscribe", "OneOffQuery", "OneOffQueryResponse" }, new[]{ "Type" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.IdentityToken), global::ClientApi.IdentityToken.Parser, new[]{ "Identity", "Token", "Address" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.FunctionCall), global::ClientApi.FunctionCall.Parser, new[]{ "Reducer", "ArgBytes", "RequestId" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Subscribe), global::ClientApi.Subscribe.Parser, new[]{ "QueryStrings", "RequestId" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.Event), global::ClientApi.Event.Parser, new[]{ "Timestamp", "CallerIdentity", "FunctionCall", "Status", "Message", "EnergyQuantaUsed", "HostExecutionDurationMicros", "CallerAddress" }, null, new[]{ typeof(global::ClientApi.Event.Types.Status) }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.SubscriptionUpdate), global::ClientApi.SubscriptionUpdate.Parser, new[]{ "TableUpdates", "RequestId", "TotalHostExecutionDurationMicros" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableUpdate), global::ClientApi.TableUpdate.Parser, new[]{ "TableId", "TableName", "TableRowOperations" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TableRowOperation), global::ClientApi.TableRowOperation.Parser, new[]{ "Op", "Row" }, null, new[]{ typeof(global::ClientApi.TableRowOperation.Types.OperationType) }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.TransactionUpdate), global::ClientApi.TransactionUpdate.Parser, new[]{ "Event", "SubscriptionUpdate" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQuery), global::ClientApi.OneOffQuery.Parser, new[]{ "MessageId", "QueryString" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffQueryResponse), global::ClientApi.OneOffQueryResponse.Parser, new[]{ "MessageId", "Error", "Tables", "TotalHostExecutionDurationMicros" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ClientApi.OneOffTable), global::ClientApi.OneOffTable.Parser, new[]{ "TableName", "Row" }, null, null, null, null) - })); - } - #endregion - - } - #region Messages - /// - /////// Generic Message ////// - /// TODO: Theoretically this format could be replaced by AlgebraicValue/AlgebraicType - /// but I don't think we want to do that yet. - /// TODO: Split this up into ServerBound and ClientBound if there's no overlap - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class Message : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Message()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Message() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Message(Message other) : this() { - switch (other.TypeCase) { - case TypeOneofCase.FunctionCall: - FunctionCall = other.FunctionCall.Clone(); - break; - case TypeOneofCase.SubscriptionUpdate: - SubscriptionUpdate = other.SubscriptionUpdate.Clone(); - break; - case TypeOneofCase.Event: - Event = other.Event.Clone(); - break; - case TypeOneofCase.TransactionUpdate: - TransactionUpdate = other.TransactionUpdate.Clone(); - break; - case TypeOneofCase.IdentityToken: - IdentityToken = other.IdentityToken.Clone(); - break; - case TypeOneofCase.Subscribe: - Subscribe = other.Subscribe.Clone(); - break; - case TypeOneofCase.OneOffQuery: - OneOffQuery = other.OneOffQuery.Clone(); - break; - case TypeOneofCase.OneOffQueryResponse: - OneOffQueryResponse = other.OneOffQueryResponse.Clone(); - break; - } - - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Message Clone() { - return new Message(this); - } - - /// Field number for the "functionCall" field. - public const int FunctionCallFieldNumber = 1; - /// - /// client -> database, request a reducer run. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.FunctionCall FunctionCall { - get { return typeCase_ == TypeOneofCase.FunctionCall ? (global::ClientApi.FunctionCall) type_ : null; } - set { - type_ = value; - typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.FunctionCall; - } - } - - /// Field number for the "subscriptionUpdate" field. - public const int SubscriptionUpdateFieldNumber = 2; - /// - /// database -> client, contained in `TransactionUpdate`, informs of changes to - /// subscribed rows. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.SubscriptionUpdate SubscriptionUpdate { - get { return typeCase_ == TypeOneofCase.SubscriptionUpdate ? (global::ClientApi.SubscriptionUpdate) type_ : null; } - set { - type_ = value; - typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.SubscriptionUpdate; - } - } - - /// Field number for the "event" field. - public const int EventFieldNumber = 3; - /// - /// database -> client, contained in `TransactionUpdate`, describes a reducer run. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.Event Event { - get { return typeCase_ == TypeOneofCase.Event ? (global::ClientApi.Event) type_ : null; } - set { - type_ = value; - typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.Event; - } - } - - /// Field number for the "transactionUpdate" field. - public const int TransactionUpdateFieldNumber = 4; - /// - /// database -> client, upon reducer run. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.TransactionUpdate TransactionUpdate { - get { return typeCase_ == TypeOneofCase.TransactionUpdate ? (global::ClientApi.TransactionUpdate) type_ : null; } - set { - type_ = value; - typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.TransactionUpdate; - } - } - - /// Field number for the "identityToken" field. - public const int IdentityTokenFieldNumber = 5; - /// - /// database -> client, after connecting, to inform client of its identity. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.IdentityToken IdentityToken { - get { return typeCase_ == TypeOneofCase.IdentityToken ? (global::ClientApi.IdentityToken) type_ : null; } - set { - type_ = value; - typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.IdentityToken; - } - } - - /// Field number for the "subscribe" field. - public const int SubscribeFieldNumber = 6; - /// - /// client -> database, register SQL queries on which to receive updates. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.Subscribe Subscribe { - get { return typeCase_ == TypeOneofCase.Subscribe ? (global::ClientApi.Subscribe) type_ : null; } - set { - type_ = value; - typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.Subscribe; - } - } - - /// Field number for the "oneOffQuery" field. - public const int OneOffQueryFieldNumber = 7; - /// - /// client -> database, send a one-off SQL query without establishing a subscription. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.OneOffQuery OneOffQuery { - get { return typeCase_ == TypeOneofCase.OneOffQuery ? (global::ClientApi.OneOffQuery) type_ : null; } - set { - type_ = value; - typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.OneOffQuery; - } - } - - /// Field number for the "oneOffQueryResponse" field. - public const int OneOffQueryResponseFieldNumber = 8; - /// - /// database -> client, return results to a one off SQL query. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.OneOffQueryResponse OneOffQueryResponse { - get { return typeCase_ == TypeOneofCase.OneOffQueryResponse ? (global::ClientApi.OneOffQueryResponse) type_ : null; } - set { - type_ = value; - typeCase_ = value == null ? TypeOneofCase.None : TypeOneofCase.OneOffQueryResponse; - } - } - - private object type_; - /// Enum of possible cases for the "type" oneof. - public enum TypeOneofCase { - None = 0, - FunctionCall = 1, - SubscriptionUpdate = 2, - Event = 3, - TransactionUpdate = 4, - IdentityToken = 5, - Subscribe = 6, - OneOffQuery = 7, - OneOffQueryResponse = 8, - } - private TypeOneofCase typeCase_ = TypeOneofCase.None; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TypeOneofCase TypeCase { - get { return typeCase_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearType() { - typeCase_ = TypeOneofCase.None; - type_ = null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as Message); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Message other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(FunctionCall, other.FunctionCall)) return false; - if (!object.Equals(SubscriptionUpdate, other.SubscriptionUpdate)) return false; - if (!object.Equals(Event, other.Event)) return false; - if (!object.Equals(TransactionUpdate, other.TransactionUpdate)) return false; - if (!object.Equals(IdentityToken, other.IdentityToken)) return false; - if (!object.Equals(Subscribe, other.Subscribe)) return false; - if (!object.Equals(OneOffQuery, other.OneOffQuery)) return false; - if (!object.Equals(OneOffQueryResponse, other.OneOffQueryResponse)) return false; - if (TypeCase != other.TypeCase) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (typeCase_ == TypeOneofCase.FunctionCall) hash ^= FunctionCall.GetHashCode(); - if (typeCase_ == TypeOneofCase.SubscriptionUpdate) hash ^= SubscriptionUpdate.GetHashCode(); - if (typeCase_ == TypeOneofCase.Event) hash ^= Event.GetHashCode(); - if (typeCase_ == TypeOneofCase.TransactionUpdate) hash ^= TransactionUpdate.GetHashCode(); - if (typeCase_ == TypeOneofCase.IdentityToken) hash ^= IdentityToken.GetHashCode(); - if (typeCase_ == TypeOneofCase.Subscribe) hash ^= Subscribe.GetHashCode(); - if (typeCase_ == TypeOneofCase.OneOffQuery) hash ^= OneOffQuery.GetHashCode(); - if (typeCase_ == TypeOneofCase.OneOffQueryResponse) hash ^= OneOffQueryResponse.GetHashCode(); - hash ^= (int) typeCase_; - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (typeCase_ == TypeOneofCase.FunctionCall) { - output.WriteRawTag(10); - output.WriteMessage(FunctionCall); - } - if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { - output.WriteRawTag(18); - output.WriteMessage(SubscriptionUpdate); - } - if (typeCase_ == TypeOneofCase.Event) { - output.WriteRawTag(26); - output.WriteMessage(Event); - } - if (typeCase_ == TypeOneofCase.TransactionUpdate) { - output.WriteRawTag(34); - output.WriteMessage(TransactionUpdate); - } - if (typeCase_ == TypeOneofCase.IdentityToken) { - output.WriteRawTag(42); - output.WriteMessage(IdentityToken); - } - if (typeCase_ == TypeOneofCase.Subscribe) { - output.WriteRawTag(50); - output.WriteMessage(Subscribe); - } - if (typeCase_ == TypeOneofCase.OneOffQuery) { - output.WriteRawTag(58); - output.WriteMessage(OneOffQuery); - } - if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { - output.WriteRawTag(66); - output.WriteMessage(OneOffQueryResponse); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (typeCase_ == TypeOneofCase.FunctionCall) { - output.WriteRawTag(10); - output.WriteMessage(FunctionCall); - } - if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { - output.WriteRawTag(18); - output.WriteMessage(SubscriptionUpdate); - } - if (typeCase_ == TypeOneofCase.Event) { - output.WriteRawTag(26); - output.WriteMessage(Event); - } - if (typeCase_ == TypeOneofCase.TransactionUpdate) { - output.WriteRawTag(34); - output.WriteMessage(TransactionUpdate); - } - if (typeCase_ == TypeOneofCase.IdentityToken) { - output.WriteRawTag(42); - output.WriteMessage(IdentityToken); - } - if (typeCase_ == TypeOneofCase.Subscribe) { - output.WriteRawTag(50); - output.WriteMessage(Subscribe); - } - if (typeCase_ == TypeOneofCase.OneOffQuery) { - output.WriteRawTag(58); - output.WriteMessage(OneOffQuery); - } - if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { - output.WriteRawTag(66); - output.WriteMessage(OneOffQueryResponse); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (typeCase_ == TypeOneofCase.FunctionCall) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(FunctionCall); - } - if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubscriptionUpdate); - } - if (typeCase_ == TypeOneofCase.Event) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Event); - } - if (typeCase_ == TypeOneofCase.TransactionUpdate) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(TransactionUpdate); - } - if (typeCase_ == TypeOneofCase.IdentityToken) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(IdentityToken); - } - if (typeCase_ == TypeOneofCase.Subscribe) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Subscribe); - } - if (typeCase_ == TypeOneofCase.OneOffQuery) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(OneOffQuery); - } - if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(OneOffQueryResponse); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Message other) { - if (other == null) { - return; - } - switch (other.TypeCase) { - case TypeOneofCase.FunctionCall: - if (FunctionCall == null) { - FunctionCall = new global::ClientApi.FunctionCall(); - } - FunctionCall.MergeFrom(other.FunctionCall); - break; - case TypeOneofCase.SubscriptionUpdate: - if (SubscriptionUpdate == null) { - SubscriptionUpdate = new global::ClientApi.SubscriptionUpdate(); - } - SubscriptionUpdate.MergeFrom(other.SubscriptionUpdate); - break; - case TypeOneofCase.Event: - if (Event == null) { - Event = new global::ClientApi.Event(); - } - Event.MergeFrom(other.Event); - break; - case TypeOneofCase.TransactionUpdate: - if (TransactionUpdate == null) { - TransactionUpdate = new global::ClientApi.TransactionUpdate(); - } - TransactionUpdate.MergeFrom(other.TransactionUpdate); - break; - case TypeOneofCase.IdentityToken: - if (IdentityToken == null) { - IdentityToken = new global::ClientApi.IdentityToken(); - } - IdentityToken.MergeFrom(other.IdentityToken); - break; - case TypeOneofCase.Subscribe: - if (Subscribe == null) { - Subscribe = new global::ClientApi.Subscribe(); - } - Subscribe.MergeFrom(other.Subscribe); - break; - case TypeOneofCase.OneOffQuery: - if (OneOffQuery == null) { - OneOffQuery = new global::ClientApi.OneOffQuery(); - } - OneOffQuery.MergeFrom(other.OneOffQuery); - break; - case TypeOneofCase.OneOffQueryResponse: - if (OneOffQueryResponse == null) { - OneOffQueryResponse = new global::ClientApi.OneOffQueryResponse(); - } - OneOffQueryResponse.MergeFrom(other.OneOffQueryResponse); - break; - } - - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 10: { - global::ClientApi.FunctionCall subBuilder = new global::ClientApi.FunctionCall(); - if (typeCase_ == TypeOneofCase.FunctionCall) { - subBuilder.MergeFrom(FunctionCall); - } - input.ReadMessage(subBuilder); - FunctionCall = subBuilder; - break; - } - case 18: { - global::ClientApi.SubscriptionUpdate subBuilder = new global::ClientApi.SubscriptionUpdate(); - if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { - subBuilder.MergeFrom(SubscriptionUpdate); - } - input.ReadMessage(subBuilder); - SubscriptionUpdate = subBuilder; - break; - } - case 26: { - global::ClientApi.Event subBuilder = new global::ClientApi.Event(); - if (typeCase_ == TypeOneofCase.Event) { - subBuilder.MergeFrom(Event); - } - input.ReadMessage(subBuilder); - Event = subBuilder; - break; - } - case 34: { - global::ClientApi.TransactionUpdate subBuilder = new global::ClientApi.TransactionUpdate(); - if (typeCase_ == TypeOneofCase.TransactionUpdate) { - subBuilder.MergeFrom(TransactionUpdate); - } - input.ReadMessage(subBuilder); - TransactionUpdate = subBuilder; - break; - } - case 42: { - global::ClientApi.IdentityToken subBuilder = new global::ClientApi.IdentityToken(); - if (typeCase_ == TypeOneofCase.IdentityToken) { - subBuilder.MergeFrom(IdentityToken); - } - input.ReadMessage(subBuilder); - IdentityToken = subBuilder; - break; - } - case 50: { - global::ClientApi.Subscribe subBuilder = new global::ClientApi.Subscribe(); - if (typeCase_ == TypeOneofCase.Subscribe) { - subBuilder.MergeFrom(Subscribe); - } - input.ReadMessage(subBuilder); - Subscribe = subBuilder; - break; - } - case 58: { - global::ClientApi.OneOffQuery subBuilder = new global::ClientApi.OneOffQuery(); - if (typeCase_ == TypeOneofCase.OneOffQuery) { - subBuilder.MergeFrom(OneOffQuery); - } - input.ReadMessage(subBuilder); - OneOffQuery = subBuilder; - break; - } - case 66: { - global::ClientApi.OneOffQueryResponse subBuilder = new global::ClientApi.OneOffQueryResponse(); - if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { - subBuilder.MergeFrom(OneOffQueryResponse); - } - input.ReadMessage(subBuilder); - OneOffQueryResponse = subBuilder; - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 10: { - global::ClientApi.FunctionCall subBuilder = new global::ClientApi.FunctionCall(); - if (typeCase_ == TypeOneofCase.FunctionCall) { - subBuilder.MergeFrom(FunctionCall); - } - input.ReadMessage(subBuilder); - FunctionCall = subBuilder; - break; - } - case 18: { - global::ClientApi.SubscriptionUpdate subBuilder = new global::ClientApi.SubscriptionUpdate(); - if (typeCase_ == TypeOneofCase.SubscriptionUpdate) { - subBuilder.MergeFrom(SubscriptionUpdate); - } - input.ReadMessage(subBuilder); - SubscriptionUpdate = subBuilder; - break; - } - case 26: { - global::ClientApi.Event subBuilder = new global::ClientApi.Event(); - if (typeCase_ == TypeOneofCase.Event) { - subBuilder.MergeFrom(Event); - } - input.ReadMessage(subBuilder); - Event = subBuilder; - break; - } - case 34: { - global::ClientApi.TransactionUpdate subBuilder = new global::ClientApi.TransactionUpdate(); - if (typeCase_ == TypeOneofCase.TransactionUpdate) { - subBuilder.MergeFrom(TransactionUpdate); - } - input.ReadMessage(subBuilder); - TransactionUpdate = subBuilder; - break; - } - case 42: { - global::ClientApi.IdentityToken subBuilder = new global::ClientApi.IdentityToken(); - if (typeCase_ == TypeOneofCase.IdentityToken) { - subBuilder.MergeFrom(IdentityToken); - } - input.ReadMessage(subBuilder); - IdentityToken = subBuilder; - break; - } - case 50: { - global::ClientApi.Subscribe subBuilder = new global::ClientApi.Subscribe(); - if (typeCase_ == TypeOneofCase.Subscribe) { - subBuilder.MergeFrom(Subscribe); - } - input.ReadMessage(subBuilder); - Subscribe = subBuilder; - break; - } - case 58: { - global::ClientApi.OneOffQuery subBuilder = new global::ClientApi.OneOffQuery(); - if (typeCase_ == TypeOneofCase.OneOffQuery) { - subBuilder.MergeFrom(OneOffQuery); - } - input.ReadMessage(subBuilder); - OneOffQuery = subBuilder; - break; - } - case 66: { - global::ClientApi.OneOffQueryResponse subBuilder = new global::ClientApi.OneOffQueryResponse(); - if (typeCase_ == TypeOneofCase.OneOffQueryResponse) { - subBuilder.MergeFrom(OneOffQueryResponse); - } - input.ReadMessage(subBuilder); - OneOffQueryResponse = subBuilder; - break; - } - } - } - } - #endif - - } - - /// - //// Received by database from client to inform of user's identity, token and client address. - //// - //// The database will always send an `IdentityToken` message - //// as the first message for a new WebSocket connection. - //// If the client is re-connecting with existing credentials, - //// the message will include those credentials. - //// If the client connected anonymously, - //// the database will generate new credentials to identify it. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class IdentityToken : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new IdentityToken()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[1]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public IdentityToken() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public IdentityToken(IdentityToken other) : this() { - identity_ = other.identity_; - token_ = other.token_; - address_ = other.address_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public IdentityToken Clone() { - return new IdentityToken(this); - } - - /// Field number for the "identity" field. - public const int IdentityFieldNumber = 1; - private pb::ByteString identity_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Identity { - get { return identity_; } - set { - identity_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "token" field. - public const int TokenFieldNumber = 2; - private string token_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Token { - get { return token_; } - set { - token_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "address" field. - public const int AddressFieldNumber = 3; - private pb::ByteString address_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Address { - get { return address_; } - set { - address_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as IdentityToken); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(IdentityToken other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Identity != other.Identity) return false; - if (Token != other.Token) return false; - if (Address != other.Address) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (Identity.Length != 0) hash ^= Identity.GetHashCode(); - if (Token.Length != 0) hash ^= Token.GetHashCode(); - if (Address.Length != 0) hash ^= Address.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (Identity.Length != 0) { - output.WriteRawTag(10); - output.WriteBytes(Identity); - } - if (Token.Length != 0) { - output.WriteRawTag(18); - output.WriteString(Token); - } - if (Address.Length != 0) { - output.WriteRawTag(26); - output.WriteBytes(Address); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (Identity.Length != 0) { - output.WriteRawTag(10); - output.WriteBytes(Identity); - } - if (Token.Length != 0) { - output.WriteRawTag(18); - output.WriteString(Token); - } - if (Address.Length != 0) { - output.WriteRawTag(26); - output.WriteBytes(Address); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (Identity.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(Identity); - } - if (Token.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Token); - } - if (Address.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(Address); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(IdentityToken other) { - if (other == null) { - return; - } - if (other.Identity.Length != 0) { - Identity = other.Identity; - } - if (other.Token.Length != 0) { - Token = other.Token; - } - if (other.Address.Length != 0) { - Address = other.Address; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 10: { - Identity = input.ReadBytes(); - break; - } - case 18: { - Token = input.ReadString(); - break; - } - case 26: { - Address = input.ReadBytes(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 10: { - Identity = input.ReadBytes(); - break; - } - case 18: { - Token = input.ReadString(); - break; - } - case 26: { - Address = input.ReadBytes(); - break; - } - } - } - } - #endif - - } - - /// - //// Sent by client to database to request a reducer runs. - //// - //// - `reducer` is the string name of a reducer to run. - //// - //// - `argBytes` is the arguments to the reducer, encoded as BSATN. - //// - //// - `requestId` is a identifier for client request. - //// SpacetimeDB models reducers as taking a single `AlgebraicValue` as an argument, which - //// generally will be a `ProductValue` containing all of the args (except the - //// `ReducerContext`, which is injected by the host, not provided in this API). - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class FunctionCall : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FunctionCall()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[2]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FunctionCall() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FunctionCall(FunctionCall other) : this() { - reducer_ = other.reducer_; - argBytes_ = other.argBytes_; - requestId_ = other.requestId_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public FunctionCall Clone() { - return new FunctionCall(this); - } - - /// Field number for the "reducer" field. - public const int ReducerFieldNumber = 1; - private string reducer_ = ""; - /// - /// TODO: Maybe this should be replaced with an int identifier for performance? - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Reducer { - get { return reducer_; } - set { - reducer_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "argBytes" field. - public const int ArgBytesFieldNumber = 2; - private pb::ByteString argBytes_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString ArgBytes { - get { return argBytes_; } - set { - argBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "requestId" field. - public const int RequestIdFieldNumber = 3; - private uint requestId_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint RequestId { - get { return requestId_; } - set { - requestId_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as FunctionCall); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(FunctionCall other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Reducer != other.Reducer) return false; - if (ArgBytes != other.ArgBytes) return false; - if (RequestId != other.RequestId) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (Reducer.Length != 0) hash ^= Reducer.GetHashCode(); - if (ArgBytes.Length != 0) hash ^= ArgBytes.GetHashCode(); - if (RequestId != 0) hash ^= RequestId.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (Reducer.Length != 0) { - output.WriteRawTag(10); - output.WriteString(Reducer); - } - if (ArgBytes.Length != 0) { - output.WriteRawTag(18); - output.WriteBytes(ArgBytes); - } - if (RequestId != 0) { - output.WriteRawTag(24); - output.WriteUInt32(RequestId); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (Reducer.Length != 0) { - output.WriteRawTag(10); - output.WriteString(Reducer); - } - if (ArgBytes.Length != 0) { - output.WriteRawTag(18); - output.WriteBytes(ArgBytes); - } - if (RequestId != 0) { - output.WriteRawTag(24); - output.WriteUInt32(RequestId); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (Reducer.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Reducer); - } - if (ArgBytes.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(ArgBytes); - } - if (RequestId != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(RequestId); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(FunctionCall other) { - if (other == null) { - return; - } - if (other.Reducer.Length != 0) { - Reducer = other.Reducer; - } - if (other.ArgBytes.Length != 0) { - ArgBytes = other.ArgBytes; - } - if (other.RequestId != 0) { - RequestId = other.RequestId; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 10: { - Reducer = input.ReadString(); - break; - } - case 18: { - ArgBytes = input.ReadBytes(); - break; - } - case 24: { - RequestId = input.ReadUInt32(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 10: { - Reducer = input.ReadString(); - break; - } - case 18: { - ArgBytes = input.ReadBytes(); - break; - } - case 24: { - RequestId = input.ReadUInt32(); - break; - } - } - } - } - #endif - - } - - /// - //// Sent by client to database to register a set of queries, about which the client will - //// receive `TransactionUpdate`s. - //// - //// `query_strings` is a sequence of strings, each of which is a SQL query. - //// - //// After issuing a `Subscribe` message, the client will receive a single - //// `SubscriptionUpdate` message containing every current row of every table which matches - //// the subscribed queries. Then, after each reducer run which updates one or more - //// subscribed rows, the client will receive a `TransactionUpdate` containing the updates. - //// - //// A `Subscribe` message sets or replaces the entire set of queries to which the client - //// is subscribed. If the client is previously subscribed to some set of queries `A`, and - //// then sends a `Subscribe` message to subscribe to a set `B`, afterwards, the client - //// will be subscribed to `B` but not `A`. In this case, the client will receive a - //// `SubscriptionUpdate` containing every existing row that matches `B`, even if some were - //// already in `A`. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class Subscribe : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Subscribe()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[3]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Subscribe() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Subscribe(Subscribe other) : this() { - queryStrings_ = other.queryStrings_.Clone(); - requestId_ = other.requestId_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Subscribe Clone() { - return new Subscribe(this); - } - - /// Field number for the "query_strings" field. - public const int QueryStringsFieldNumber = 1; - private static readonly pb::FieldCodec _repeated_queryStrings_codec - = pb::FieldCodec.ForString(10); - private readonly pbc::RepeatedField queryStrings_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField QueryStrings { - get { return queryStrings_; } - } - - /// Field number for the "requestId" field. - public const int RequestIdFieldNumber = 2; - private uint requestId_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint RequestId { - get { return requestId_; } - set { - requestId_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as Subscribe); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Subscribe other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if(!queryStrings_.Equals(other.queryStrings_)) return false; - if (RequestId != other.RequestId) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - hash ^= queryStrings_.GetHashCode(); - if (RequestId != 0) hash ^= RequestId.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - queryStrings_.WriteTo(output, _repeated_queryStrings_codec); - if (RequestId != 0) { - output.WriteRawTag(16); - output.WriteUInt32(RequestId); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - queryStrings_.WriteTo(ref output, _repeated_queryStrings_codec); - if (RequestId != 0) { - output.WriteRawTag(16); - output.WriteUInt32(RequestId); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - size += queryStrings_.CalculateSize(_repeated_queryStrings_codec); - if (RequestId != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(RequestId); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Subscribe other) { - if (other == null) { - return; - } - queryStrings_.Add(other.queryStrings_); - if (other.RequestId != 0) { - RequestId = other.RequestId; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 10: { - queryStrings_.AddEntriesFrom(input, _repeated_queryStrings_codec); - break; - } - case 16: { - RequestId = input.ReadUInt32(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 10: { - queryStrings_.AddEntriesFrom(ref input, _repeated_queryStrings_codec); - break; - } - case 16: { - RequestId = input.ReadUInt32(); - break; - } - } - } - } - #endif - - } - - /// - //// Part of a `TransactionUpdate` received by client from database upon a reducer run. - //// - //// - `timestamp` is the time when the reducer started, - //// as microseconds since the Unix epoch. - //// - //// - `callerIdentity` is the identity of the user who requested the reducer run. - //// For event-driven and scheduled reducers, - //// it is the identity of the database owner. - //// - //// - `functionCall` contains the name of the reducer which ran and the arguments it - //// received. - //// - //// - `status` of `committed` means that the reducer ran successfully and its changes were - //// committed to the database. The rows altered in the database - //// will be recorded in the parent `TransactionUpdate`'s - //// `SubscriptionUpdate`. - //// - //// - `status` of `failed` means that the reducer panicked, and any changes it attempted to - //// make were rolled back. - //// - //// - `status` of `out_of_energy` means that the reducer was interrupted - //// due to insufficient energy/funds, - //// and any changes it attempted to make were rolled back. - //// - //// - `message` is the error message with which the reducer failed. - //// For `committed` or `out_of_energy` statuses, - //// it is the empty string. - //// - //// - `energy_quanta_used` and `host_execution_duration_micros` seem self-explanatory; - //// they describe the amount of energy credits consumed by running the reducer, - //// and how long it took to run. - //// - //// - `callerAddress` is the 16-byte address of the user who requested the reducer run. - //// The all-zeros address is a sentinel which denotes no address. - //// `init` and `update` reducers will have a `callerAddress` - //// if and only if one was provided to the `publish` HTTP endpoint. - //// Scheduled reducers will never have a `callerAddress`. - //// Reducers invoked by HTTP will have a `callerAddress` - //// if and only if one was provided to the `call` HTTP endpoint. - //// Reducers invoked by WebSocket will always have a `callerAddress`. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class Event : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Event()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[4]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Event() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Event(Event other) : this() { - timestamp_ = other.timestamp_; - callerIdentity_ = other.callerIdentity_; - functionCall_ = other.functionCall_ != null ? other.functionCall_.Clone() : null; - status_ = other.status_; - message_ = other.message_; - energyQuantaUsed_ = other.energyQuantaUsed_; - hostExecutionDurationMicros_ = other.hostExecutionDurationMicros_; - callerAddress_ = other.callerAddress_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public Event Clone() { - return new Event(this); - } - - /// Field number for the "timestamp" field. - public const int TimestampFieldNumber = 1; - private ulong timestamp_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong Timestamp { - get { return timestamp_; } - set { - timestamp_ = value; - } - } - - /// Field number for the "callerIdentity" field. - public const int CallerIdentityFieldNumber = 2; - private pb::ByteString callerIdentity_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString CallerIdentity { - get { return callerIdentity_; } - set { - callerIdentity_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "functionCall" field. - public const int FunctionCallFieldNumber = 3; - private global::ClientApi.FunctionCall functionCall_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.FunctionCall FunctionCall { - get { return functionCall_; } - set { - functionCall_ = value; - } - } - - /// Field number for the "status" field. - public const int StatusFieldNumber = 4; - private global::ClientApi.Event.Types.Status status_ = global::ClientApi.Event.Types.Status.Committed; - /// - /// TODO: arguably these should go inside an EventStatus message - /// since success doesn't have a message - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.Event.Types.Status Status { - get { return status_; } - set { - status_ = value; - } - } - - /// Field number for the "message" field. - public const int MessageFieldNumber = 5; - private string message_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Message { - get { return message_; } - set { - message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "energy_quanta_used" field. - public const int EnergyQuantaUsedFieldNumber = 6; - private long energyQuantaUsed_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public long EnergyQuantaUsed { - get { return energyQuantaUsed_; } - set { - energyQuantaUsed_ = value; - } - } - - /// Field number for the "host_execution_duration_micros" field. - public const int HostExecutionDurationMicrosFieldNumber = 7; - private ulong hostExecutionDurationMicros_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong HostExecutionDurationMicros { - get { return hostExecutionDurationMicros_; } - set { - hostExecutionDurationMicros_ = value; - } - } - - /// Field number for the "callerAddress" field. - public const int CallerAddressFieldNumber = 8; - private pb::ByteString callerAddress_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString CallerAddress { - get { return callerAddress_; } - set { - callerAddress_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as Event); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(Event other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Timestamp != other.Timestamp) return false; - if (CallerIdentity != other.CallerIdentity) return false; - if (!object.Equals(FunctionCall, other.FunctionCall)) return false; - if (Status != other.Status) return false; - if (Message != other.Message) return false; - if (EnergyQuantaUsed != other.EnergyQuantaUsed) return false; - if (HostExecutionDurationMicros != other.HostExecutionDurationMicros) return false; - if (CallerAddress != other.CallerAddress) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (Timestamp != 0UL) hash ^= Timestamp.GetHashCode(); - if (CallerIdentity.Length != 0) hash ^= CallerIdentity.GetHashCode(); - if (functionCall_ != null) hash ^= FunctionCall.GetHashCode(); - if (Status != global::ClientApi.Event.Types.Status.Committed) hash ^= Status.GetHashCode(); - if (Message.Length != 0) hash ^= Message.GetHashCode(); - if (EnergyQuantaUsed != 0L) hash ^= EnergyQuantaUsed.GetHashCode(); - if (HostExecutionDurationMicros != 0UL) hash ^= HostExecutionDurationMicros.GetHashCode(); - if (CallerAddress.Length != 0) hash ^= CallerAddress.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (Timestamp != 0UL) { - output.WriteRawTag(8); - output.WriteUInt64(Timestamp); - } - if (CallerIdentity.Length != 0) { - output.WriteRawTag(18); - output.WriteBytes(CallerIdentity); - } - if (functionCall_ != null) { - output.WriteRawTag(26); - output.WriteMessage(FunctionCall); - } - if (Status != global::ClientApi.Event.Types.Status.Committed) { - output.WriteRawTag(32); - output.WriteEnum((int) Status); - } - if (Message.Length != 0) { - output.WriteRawTag(42); - output.WriteString(Message); - } - if (EnergyQuantaUsed != 0L) { - output.WriteRawTag(48); - output.WriteInt64(EnergyQuantaUsed); - } - if (HostExecutionDurationMicros != 0UL) { - output.WriteRawTag(56); - output.WriteUInt64(HostExecutionDurationMicros); - } - if (CallerAddress.Length != 0) { - output.WriteRawTag(66); - output.WriteBytes(CallerAddress); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (Timestamp != 0UL) { - output.WriteRawTag(8); - output.WriteUInt64(Timestamp); - } - if (CallerIdentity.Length != 0) { - output.WriteRawTag(18); - output.WriteBytes(CallerIdentity); - } - if (functionCall_ != null) { - output.WriteRawTag(26); - output.WriteMessage(FunctionCall); - } - if (Status != global::ClientApi.Event.Types.Status.Committed) { - output.WriteRawTag(32); - output.WriteEnum((int) Status); - } - if (Message.Length != 0) { - output.WriteRawTag(42); - output.WriteString(Message); - } - if (EnergyQuantaUsed != 0L) { - output.WriteRawTag(48); - output.WriteInt64(EnergyQuantaUsed); - } - if (HostExecutionDurationMicros != 0UL) { - output.WriteRawTag(56); - output.WriteUInt64(HostExecutionDurationMicros); - } - if (CallerAddress.Length != 0) { - output.WriteRawTag(66); - output.WriteBytes(CallerAddress); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (Timestamp != 0UL) { - size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Timestamp); - } - if (CallerIdentity.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(CallerIdentity); - } - if (functionCall_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(FunctionCall); - } - if (Status != global::ClientApi.Event.Types.Status.Committed) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status); - } - if (Message.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); - } - if (EnergyQuantaUsed != 0L) { - size += 1 + pb::CodedOutputStream.ComputeInt64Size(EnergyQuantaUsed); - } - if (HostExecutionDurationMicros != 0UL) { - size += 1 + pb::CodedOutputStream.ComputeUInt64Size(HostExecutionDurationMicros); - } - if (CallerAddress.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(CallerAddress); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(Event other) { - if (other == null) { - return; - } - if (other.Timestamp != 0UL) { - Timestamp = other.Timestamp; - } - if (other.CallerIdentity.Length != 0) { - CallerIdentity = other.CallerIdentity; - } - if (other.functionCall_ != null) { - if (functionCall_ == null) { - FunctionCall = new global::ClientApi.FunctionCall(); - } - FunctionCall.MergeFrom(other.FunctionCall); - } - if (other.Status != global::ClientApi.Event.Types.Status.Committed) { - Status = other.Status; - } - if (other.Message.Length != 0) { - Message = other.Message; - } - if (other.EnergyQuantaUsed != 0L) { - EnergyQuantaUsed = other.EnergyQuantaUsed; - } - if (other.HostExecutionDurationMicros != 0UL) { - HostExecutionDurationMicros = other.HostExecutionDurationMicros; - } - if (other.CallerAddress.Length != 0) { - CallerAddress = other.CallerAddress; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 8: { - Timestamp = input.ReadUInt64(); - break; - } - case 18: { - CallerIdentity = input.ReadBytes(); - break; - } - case 26: { - if (functionCall_ == null) { - FunctionCall = new global::ClientApi.FunctionCall(); - } - input.ReadMessage(FunctionCall); - break; - } - case 32: { - Status = (global::ClientApi.Event.Types.Status) input.ReadEnum(); - break; - } - case 42: { - Message = input.ReadString(); - break; - } - case 48: { - EnergyQuantaUsed = input.ReadInt64(); - break; - } - case 56: { - HostExecutionDurationMicros = input.ReadUInt64(); - break; - } - case 66: { - CallerAddress = input.ReadBytes(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 8: { - Timestamp = input.ReadUInt64(); - break; - } - case 18: { - CallerIdentity = input.ReadBytes(); - break; - } - case 26: { - if (functionCall_ == null) { - FunctionCall = new global::ClientApi.FunctionCall(); - } - input.ReadMessage(FunctionCall); - break; - } - case 32: { - Status = (global::ClientApi.Event.Types.Status) input.ReadEnum(); - break; - } - case 42: { - Message = input.ReadString(); - break; - } - case 48: { - EnergyQuantaUsed = input.ReadInt64(); - break; - } - case 56: { - HostExecutionDurationMicros = input.ReadUInt64(); - break; - } - case 66: { - CallerAddress = input.ReadBytes(); - break; - } - } - } - } - #endif - - #region Nested types - /// Container for nested types declared in the Event message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum Status { - [pbr::OriginalName("committed")] Committed = 0, - [pbr::OriginalName("failed")] Failed = 1, - [pbr::OriginalName("out_of_energy")] OutOfEnergy = 2, - } - - } - #endregion - - } - - /// - //// Part of a `TransactionUpdate` received by client from database when subscribed rows in - //// a table are altered, or received alone after a `Subscription` to initialize the - //// client's mirror of the database. - //// - //// A single `SubscriptionUpdate` may contain `TableUpdate` messages for multiple - //// tables. - //// - `requestId` is identifier sent by the client in requests, Host should ensure to - //// to include the same requestId in the response. - //// - //// - `total_host_execution_duration_micros` its the overall time between Host recevived a request - //// and sent a `TransactionUpdate` or `SubscriptionUpdate`. - //// '0' is default value. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class SubscriptionUpdate : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubscriptionUpdate()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[5]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public SubscriptionUpdate() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public SubscriptionUpdate(SubscriptionUpdate other) : this() { - tableUpdates_ = other.tableUpdates_.Clone(); - requestId_ = other.requestId_; - totalHostExecutionDurationMicros_ = other.totalHostExecutionDurationMicros_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public SubscriptionUpdate Clone() { - return new SubscriptionUpdate(this); - } - - /// Field number for the "tableUpdates" field. - public const int TableUpdatesFieldNumber = 1; - private static readonly pb::FieldCodec _repeated_tableUpdates_codec - = pb::FieldCodec.ForMessage(10, global::ClientApi.TableUpdate.Parser); - private readonly pbc::RepeatedField tableUpdates_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField TableUpdates { - get { return tableUpdates_; } - } - - /// Field number for the "requestId" field. - public const int RequestIdFieldNumber = 2; - private uint requestId_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint RequestId { - get { return requestId_; } - set { - requestId_ = value; - } - } - - /// Field number for the "total_host_execution_duration_micros" field. - public const int TotalHostExecutionDurationMicrosFieldNumber = 3; - private ulong totalHostExecutionDurationMicros_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong TotalHostExecutionDurationMicros { - get { return totalHostExecutionDurationMicros_; } - set { - totalHostExecutionDurationMicros_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as SubscriptionUpdate); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(SubscriptionUpdate other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if(!tableUpdates_.Equals(other.tableUpdates_)) return false; - if (RequestId != other.RequestId) return false; - if (TotalHostExecutionDurationMicros != other.TotalHostExecutionDurationMicros) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - hash ^= tableUpdates_.GetHashCode(); - if (RequestId != 0) hash ^= RequestId.GetHashCode(); - if (TotalHostExecutionDurationMicros != 0UL) hash ^= TotalHostExecutionDurationMicros.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - tableUpdates_.WriteTo(output, _repeated_tableUpdates_codec); - if (RequestId != 0) { - output.WriteRawTag(16); - output.WriteUInt32(RequestId); - } - if (TotalHostExecutionDurationMicros != 0UL) { - output.WriteRawTag(24); - output.WriteUInt64(TotalHostExecutionDurationMicros); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - tableUpdates_.WriteTo(ref output, _repeated_tableUpdates_codec); - if (RequestId != 0) { - output.WriteRawTag(16); - output.WriteUInt32(RequestId); - } - if (TotalHostExecutionDurationMicros != 0UL) { - output.WriteRawTag(24); - output.WriteUInt64(TotalHostExecutionDurationMicros); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - size += tableUpdates_.CalculateSize(_repeated_tableUpdates_codec); - if (RequestId != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(RequestId); - } - if (TotalHostExecutionDurationMicros != 0UL) { - size += 1 + pb::CodedOutputStream.ComputeUInt64Size(TotalHostExecutionDurationMicros); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(SubscriptionUpdate other) { - if (other == null) { - return; - } - tableUpdates_.Add(other.tableUpdates_); - if (other.RequestId != 0) { - RequestId = other.RequestId; - } - if (other.TotalHostExecutionDurationMicros != 0UL) { - TotalHostExecutionDurationMicros = other.TotalHostExecutionDurationMicros; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 10: { - tableUpdates_.AddEntriesFrom(input, _repeated_tableUpdates_codec); - break; - } - case 16: { - RequestId = input.ReadUInt32(); - break; - } - case 24: { - TotalHostExecutionDurationMicros = input.ReadUInt64(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 10: { - tableUpdates_.AddEntriesFrom(ref input, _repeated_tableUpdates_codec); - break; - } - case 16: { - RequestId = input.ReadUInt32(); - break; - } - case 24: { - TotalHostExecutionDurationMicros = input.ReadUInt64(); - break; - } - } - } - } - #endif - - } - - /// - //// Part of a `SubscriptionUpdate` received by client from database for alterations to a - //// single table. - //// - //// `tableId` and `tableName` identify the table. Clients should use the `tableName`, as - //// it is a stable part of a module's API, whereas `tableId` may - //// or may not change between runs. - //// - //// `tableRowOperations` are actual modified rows. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class TableUpdate : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TableUpdate()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[6]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TableUpdate() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TableUpdate(TableUpdate other) : this() { - tableId_ = other.tableId_; - tableName_ = other.tableName_; - tableRowOperations_ = other.tableRowOperations_.Clone(); - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TableUpdate Clone() { - return new TableUpdate(this); - } - - /// Field number for the "tableId" field. - public const int TableIdFieldNumber = 1; - private uint tableId_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public uint TableId { - get { return tableId_; } - set { - tableId_ = value; - } - } - - /// Field number for the "tableName" field. - public const int TableNameFieldNumber = 2; - private string tableName_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string TableName { - get { return tableName_; } - set { - tableName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "tableRowOperations" field. - public const int TableRowOperationsFieldNumber = 3; - private static readonly pb::FieldCodec _repeated_tableRowOperations_codec - = pb::FieldCodec.ForMessage(26, global::ClientApi.TableRowOperation.Parser); - private readonly pbc::RepeatedField tableRowOperations_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField TableRowOperations { - get { return tableRowOperations_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as TableUpdate); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(TableUpdate other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (TableId != other.TableId) return false; - if (TableName != other.TableName) return false; - if(!tableRowOperations_.Equals(other.tableRowOperations_)) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (TableId != 0) hash ^= TableId.GetHashCode(); - if (TableName.Length != 0) hash ^= TableName.GetHashCode(); - hash ^= tableRowOperations_.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (TableId != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TableId); - } - if (TableName.Length != 0) { - output.WriteRawTag(18); - output.WriteString(TableName); - } - tableRowOperations_.WriteTo(output, _repeated_tableRowOperations_codec); - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (TableId != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TableId); - } - if (TableName.Length != 0) { - output.WriteRawTag(18); - output.WriteString(TableName); - } - tableRowOperations_.WriteTo(ref output, _repeated_tableRowOperations_codec); - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (TableId != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TableId); - } - if (TableName.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(TableName); - } - size += tableRowOperations_.CalculateSize(_repeated_tableRowOperations_codec); - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(TableUpdate other) { - if (other == null) { - return; - } - if (other.TableId != 0) { - TableId = other.TableId; - } - if (other.TableName.Length != 0) { - TableName = other.TableName; - } - tableRowOperations_.Add(other.tableRowOperations_); - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 8: { - TableId = input.ReadUInt32(); - break; - } - case 18: { - TableName = input.ReadString(); - break; - } - case 26: { - tableRowOperations_.AddEntriesFrom(input, _repeated_tableRowOperations_codec); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 8: { - TableId = input.ReadUInt32(); - break; - } - case 18: { - TableName = input.ReadString(); - break; - } - case 26: { - tableRowOperations_.AddEntriesFrom(ref input, _repeated_tableRowOperations_codec); - break; - } - } - } - } - #endif - - } - - /// - //// Part of a `TableUpdate` received by client from database for alteration to a single - //// row of a table. - //// - //// The table being altered is identified by the parent `TableUpdate`. - //// - //// - `op` of `DELETE` means that the row in question has been removed and is no longer - //// resident in the table. - //// - //// - `op` of `INSERT` means that the row in question has been either newly inserted or - //// updated, and is resident in the table. - //// - //// - `row` is the row itself, encoded as BSATN. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class TableRowOperation : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TableRowOperation()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[7]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TableRowOperation() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TableRowOperation(TableRowOperation other) : this() { - op_ = other.op_; - row_ = other.row_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TableRowOperation Clone() { - return new TableRowOperation(this); - } - - /// Field number for the "op" field. - public const int OpFieldNumber = 1; - private global::ClientApi.TableRowOperation.Types.OperationType op_ = global::ClientApi.TableRowOperation.Types.OperationType.Delete; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.TableRowOperation.Types.OperationType Op { - get { return op_; } - set { - op_ = value; - } - } - - /// Field number for the "row" field. - public const int RowFieldNumber = 3; - private pb::ByteString row_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString Row { - get { return row_; } - set { - row_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as TableRowOperation); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(TableRowOperation other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Op != other.Op) return false; - if (Row != other.Row) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) hash ^= Op.GetHashCode(); - if (Row.Length != 0) hash ^= Row.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { - output.WriteRawTag(8); - output.WriteEnum((int) Op); - } - if (Row.Length != 0) { - output.WriteRawTag(26); - output.WriteBytes(Row); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { - output.WriteRawTag(8); - output.WriteEnum((int) Op); - } - if (Row.Length != 0) { - output.WriteRawTag(26); - output.WriteBytes(Row); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Op); - } - if (Row.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(Row); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(TableRowOperation other) { - if (other == null) { - return; - } - if (other.Op != global::ClientApi.TableRowOperation.Types.OperationType.Delete) { - Op = other.Op; - } - if (other.Row.Length != 0) { - Row = other.Row; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 8: { - Op = (global::ClientApi.TableRowOperation.Types.OperationType) input.ReadEnum(); - break; - } - case 26: { - Row = input.ReadBytes(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 8: { - Op = (global::ClientApi.TableRowOperation.Types.OperationType) input.ReadEnum(); - break; - } - case 26: { - Row = input.ReadBytes(); - break; - } - } - } - } - #endif - - #region Nested types - /// Container for nested types declared in the TableRowOperation message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum OperationType { - [pbr::OriginalName("DELETE")] Delete = 0, - [pbr::OriginalName("INSERT")] Insert = 1, - } - - } - #endregion - - } - - /// - //// Received by client from database upon a reducer run. - //// - //// Clients receive `TransactionUpdate`s only for reducers - //// which update at least one of their subscribed rows, - //// or for their own `failed` or `out_of_energy` reducer invocations. - //// - //// - `event` contains information about the reducer. - //// - //// - `subscriptionUpdate` contains changes to subscribed rows. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class TransactionUpdate : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TransactionUpdate()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[8]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TransactionUpdate() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TransactionUpdate(TransactionUpdate other) : this() { - event_ = other.event_ != null ? other.event_.Clone() : null; - subscriptionUpdate_ = other.subscriptionUpdate_ != null ? other.subscriptionUpdate_.Clone() : null; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public TransactionUpdate Clone() { - return new TransactionUpdate(this); - } - - /// Field number for the "event" field. - public const int EventFieldNumber = 1; - private global::ClientApi.Event event_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.Event Event { - get { return event_; } - set { - event_ = value; - } - } - - /// Field number for the "subscriptionUpdate" field. - public const int SubscriptionUpdateFieldNumber = 2; - private global::ClientApi.SubscriptionUpdate subscriptionUpdate_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::ClientApi.SubscriptionUpdate SubscriptionUpdate { - get { return subscriptionUpdate_; } - set { - subscriptionUpdate_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as TransactionUpdate); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(TransactionUpdate other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(Event, other.Event)) return false; - if (!object.Equals(SubscriptionUpdate, other.SubscriptionUpdate)) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (event_ != null) hash ^= Event.GetHashCode(); - if (subscriptionUpdate_ != null) hash ^= SubscriptionUpdate.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (event_ != null) { - output.WriteRawTag(10); - output.WriteMessage(Event); - } - if (subscriptionUpdate_ != null) { - output.WriteRawTag(18); - output.WriteMessage(SubscriptionUpdate); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (event_ != null) { - output.WriteRawTag(10); - output.WriteMessage(Event); - } - if (subscriptionUpdate_ != null) { - output.WriteRawTag(18); - output.WriteMessage(SubscriptionUpdate); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (event_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Event); - } - if (subscriptionUpdate_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubscriptionUpdate); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(TransactionUpdate other) { - if (other == null) { - return; - } - if (other.event_ != null) { - if (event_ == null) { - Event = new global::ClientApi.Event(); - } - Event.MergeFrom(other.Event); - } - if (other.subscriptionUpdate_ != null) { - if (subscriptionUpdate_ == null) { - SubscriptionUpdate = new global::ClientApi.SubscriptionUpdate(); - } - SubscriptionUpdate.MergeFrom(other.SubscriptionUpdate); - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 10: { - if (event_ == null) { - Event = new global::ClientApi.Event(); - } - input.ReadMessage(Event); - break; - } - case 18: { - if (subscriptionUpdate_ == null) { - SubscriptionUpdate = new global::ClientApi.SubscriptionUpdate(); - } - input.ReadMessage(SubscriptionUpdate); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 10: { - if (event_ == null) { - Event = new global::ClientApi.Event(); - } - input.ReadMessage(Event); - break; - } - case 18: { - if (subscriptionUpdate_ == null) { - SubscriptionUpdate = new global::ClientApi.SubscriptionUpdate(); - } - input.ReadMessage(SubscriptionUpdate); - break; - } - } - } - } - #endif - - } - - /// - //// A one-off query submission. - //// - //// Query should be a "SELECT * FROM Table WHERE ...". Other types of queries will be rejected. - //// Multiple such semicolon-delimited queries are allowed. - //// - //// One-off queries are identified by a client-generated messageID. - //// To avoid data leaks, the server will NOT cache responses to messages based on UUID! - //// It also will not check for duplicate IDs. They are just a way to match responses to messages. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class OneOffQuery : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneOffQuery()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[9]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffQuery() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffQuery(OneOffQuery other) : this() { - messageId_ = other.messageId_; - queryString_ = other.queryString_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffQuery Clone() { - return new OneOffQuery(this); - } - - /// Field number for the "messageId" field. - public const int MessageIdFieldNumber = 1; - private pb::ByteString messageId_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString MessageId { - get { return messageId_; } - set { - messageId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "queryString" field. - public const int QueryStringFieldNumber = 2; - private string queryString_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string QueryString { - get { return queryString_; } - set { - queryString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as OneOffQuery); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(OneOffQuery other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (MessageId != other.MessageId) return false; - if (QueryString != other.QueryString) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (MessageId.Length != 0) hash ^= MessageId.GetHashCode(); - if (QueryString.Length != 0) hash ^= QueryString.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (MessageId.Length != 0) { - output.WriteRawTag(10); - output.WriteBytes(MessageId); - } - if (QueryString.Length != 0) { - output.WriteRawTag(18); - output.WriteString(QueryString); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (MessageId.Length != 0) { - output.WriteRawTag(10); - output.WriteBytes(MessageId); - } - if (QueryString.Length != 0) { - output.WriteRawTag(18); - output.WriteString(QueryString); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (MessageId.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(MessageId); - } - if (QueryString.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(QueryString); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(OneOffQuery other) { - if (other == null) { - return; - } - if (other.MessageId.Length != 0) { - MessageId = other.MessageId; - } - if (other.QueryString.Length != 0) { - QueryString = other.QueryString; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 10: { - MessageId = input.ReadBytes(); - break; - } - case 18: { - QueryString = input.ReadString(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 10: { - MessageId = input.ReadBytes(); - break; - } - case 18: { - QueryString = input.ReadString(); - break; - } - } - } - } - #endif - - } - - /// - //// A one-off query response. - //// Will contain either one error or multiple response rows. - //// At most one of these messages will be sent in reply to any query. - //// - //// The messageId will be identical to the one sent in the original query. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class OneOffQueryResponse : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneOffQueryResponse()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[10]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffQueryResponse() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffQueryResponse(OneOffQueryResponse other) : this() { - messageId_ = other.messageId_; - error_ = other.error_; - tables_ = other.tables_.Clone(); - totalHostExecutionDurationMicros_ = other.totalHostExecutionDurationMicros_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffQueryResponse Clone() { - return new OneOffQueryResponse(this); - } - - /// Field number for the "messageId" field. - public const int MessageIdFieldNumber = 1; - private pb::ByteString messageId_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pb::ByteString MessageId { - get { return messageId_; } - set { - messageId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "error" field. - public const int ErrorFieldNumber = 2; - private string error_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string Error { - get { return error_; } - set { - error_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "tables" field. - public const int TablesFieldNumber = 3; - private static readonly pb::FieldCodec _repeated_tables_codec - = pb::FieldCodec.ForMessage(26, global::ClientApi.OneOffTable.Parser); - private readonly pbc::RepeatedField tables_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Tables { - get { return tables_; } - } - - /// Field number for the "total_host_execution_duration_micros" field. - public const int TotalHostExecutionDurationMicrosFieldNumber = 4; - private ulong totalHostExecutionDurationMicros_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public ulong TotalHostExecutionDurationMicros { - get { return totalHostExecutionDurationMicros_; } - set { - totalHostExecutionDurationMicros_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as OneOffQueryResponse); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(OneOffQueryResponse other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (MessageId != other.MessageId) return false; - if (Error != other.Error) return false; - if(!tables_.Equals(other.tables_)) return false; - if (TotalHostExecutionDurationMicros != other.TotalHostExecutionDurationMicros) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (MessageId.Length != 0) hash ^= MessageId.GetHashCode(); - if (Error.Length != 0) hash ^= Error.GetHashCode(); - hash ^= tables_.GetHashCode(); - if (TotalHostExecutionDurationMicros != 0UL) hash ^= TotalHostExecutionDurationMicros.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (MessageId.Length != 0) { - output.WriteRawTag(10); - output.WriteBytes(MessageId); - } - if (Error.Length != 0) { - output.WriteRawTag(18); - output.WriteString(Error); - } - tables_.WriteTo(output, _repeated_tables_codec); - if (TotalHostExecutionDurationMicros != 0UL) { - output.WriteRawTag(32); - output.WriteUInt64(TotalHostExecutionDurationMicros); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (MessageId.Length != 0) { - output.WriteRawTag(10); - output.WriteBytes(MessageId); - } - if (Error.Length != 0) { - output.WriteRawTag(18); - output.WriteString(Error); - } - tables_.WriteTo(ref output, _repeated_tables_codec); - if (TotalHostExecutionDurationMicros != 0UL) { - output.WriteRawTag(32); - output.WriteUInt64(TotalHostExecutionDurationMicros); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (MessageId.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(MessageId); - } - if (Error.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Error); - } - size += tables_.CalculateSize(_repeated_tables_codec); - if (TotalHostExecutionDurationMicros != 0UL) { - size += 1 + pb::CodedOutputStream.ComputeUInt64Size(TotalHostExecutionDurationMicros); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(OneOffQueryResponse other) { - if (other == null) { - return; - } - if (other.MessageId.Length != 0) { - MessageId = other.MessageId; - } - if (other.Error.Length != 0) { - Error = other.Error; - } - tables_.Add(other.tables_); - if (other.TotalHostExecutionDurationMicros != 0UL) { - TotalHostExecutionDurationMicros = other.TotalHostExecutionDurationMicros; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 10: { - MessageId = input.ReadBytes(); - break; - } - case 18: { - Error = input.ReadString(); - break; - } - case 26: { - tables_.AddEntriesFrom(input, _repeated_tables_codec); - break; - } - case 32: { - TotalHostExecutionDurationMicros = input.ReadUInt64(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 10: { - MessageId = input.ReadBytes(); - break; - } - case 18: { - Error = input.ReadString(); - break; - } - case 26: { - tables_.AddEntriesFrom(ref input, _repeated_tables_codec); - break; - } - case 32: { - TotalHostExecutionDurationMicros = input.ReadUInt64(); - break; - } - } - } - } - #endif - - } - - /// - //// A table included as part of a one-off query. - /// - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class OneOffTable : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneOffTable()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::ClientApi.ClientApiReflection.Descriptor.MessageTypes[11]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffTable() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffTable(OneOffTable other) : this() { - tableName_ = other.tableName_; - row_ = other.row_.Clone(); - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public OneOffTable Clone() { - return new OneOffTable(this); - } - - /// Field number for the "tableName" field. - public const int TableNameFieldNumber = 2; - private string tableName_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string TableName { - get { return tableName_; } - set { - tableName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "row" field. - public const int RowFieldNumber = 4; - private static readonly pb::FieldCodec _repeated_row_codec - = pb::FieldCodec.ForBytes(34); - private readonly pbc::RepeatedField row_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Row { - get { return row_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as OneOffTable); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(OneOffTable other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (TableName != other.TableName) return false; - if(!row_.Equals(other.row_)) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (TableName.Length != 0) hash ^= TableName.GetHashCode(); - hash ^= row_.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (TableName.Length != 0) { - output.WriteRawTag(18); - output.WriteString(TableName); - } - row_.WriteTo(output, _repeated_row_codec); - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (TableName.Length != 0) { - output.WriteRawTag(18); - output.WriteString(TableName); - } - row_.WriteTo(ref output, _repeated_row_codec); - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (TableName.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(TableName); - } - size += row_.CalculateSize(_repeated_row_codec); - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(OneOffTable other) { - if (other == null) { - return; - } - if (other.TableName.Length != 0) { - TableName = other.TableName; - } - row_.Add(other.row_); - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 18: { - TableName = input.ReadString(); - break; - } - case 34: { - row_.AddEntriesFrom(input, _repeated_row_codec); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 18: { - TableName = input.ReadString(); - break; - } - case 34: { - row_.AddEntriesFrom(ref input, _repeated_row_codec); - break; - } - } - } - } - #endif - - } - - #endregion - -} - -#endregion Designer generated code diff --git a/sdks/csharp/src/ClientApiExtensions.cs b/sdks/csharp/src/ClientApiExtensions.cs deleted file mode 100644 index 5f56bf2c3d6..00000000000 --- a/sdks/csharp/src/ClientApiExtensions.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ClientApi -{ - public partial class FunctionCall - { - public SpacetimeDB.ReducerEventBase? CallInfo { get; set; } - } -} diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index c4a664e74bc..719a6326048 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using SpacetimeDB.BSATN; -using Google.Protobuf; +using SpacetimeDB.ClientApi; namespace SpacetimeDB { @@ -14,7 +14,7 @@ public interface ITableCache : IEnumerable> Type ClientTableType { get; } bool InsertEntry(byte[] rowBytes, IDatabaseTable value); bool DeleteEntry(byte[] rowBytes); - IDatabaseTable DecodeValue(ByteString bytes); + IDatabaseTable DecodeValue(byte[] bytes); } public class TableCache : ITableCache @@ -49,7 +49,7 @@ public bool DeleteEntry(byte[] rowBytes) } // The function to use for decoding a type value. - public IDatabaseTable DecodeValue(ByteString bytes) => BSATNHelpers.FromProtoBytes(bytes); + public IDatabaseTable DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); public IEnumerator> GetEnumerator() => Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)).GetEnumerator(); diff --git a/sdks/csharp/src/IDatabaseTable.cs b/sdks/csharp/src/IDatabaseTable.cs index 57435bfde8f..5e78f922c39 100644 --- a/sdks/csharp/src/IDatabaseTable.cs +++ b/sdks/csharp/src/IDatabaseTable.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; namespace SpacetimeDB { @@ -9,9 +10,9 @@ public interface IDatabaseTable { void InternalOnValueInserted(); void InternalOnValueDeleted(); - void OnInsertEvent(ClientApi.Event? dbEvent); - void OnBeforeDeleteEvent(ClientApi.Event? dbEvent); - void OnDeleteEvent(ClientApi.Event? dbEvent); + void OnInsertEvent(ReducerEventBase? update); + void OnBeforeDeleteEvent(ReducerEventBase? update); + void OnDeleteEvent(ReducerEventBase? update); } public abstract class DatabaseTable : IDatabaseTable @@ -43,25 +44,25 @@ public static int Count() public static event DeleteEventHandler? OnBeforeDelete; public static event DeleteEventHandler? OnDelete; - public void OnInsertEvent(ClientApi.Event? dbEvent) + public void OnInsertEvent(ReducerEventBase? dbEvent) { - OnInsert?.Invoke((T)this, (ReducerEvent?)dbEvent?.FunctionCall.CallInfo); + OnInsert?.Invoke((T)this, (ReducerEvent?)dbEvent); } - public void OnBeforeDeleteEvent(ClientApi.Event? dbEvent) + public void OnBeforeDeleteEvent(ReducerEventBase? dbEvent) { - OnBeforeDelete?.Invoke((T)this, (ReducerEvent?)dbEvent?.FunctionCall.CallInfo); + OnBeforeDelete?.Invoke((T)this, (ReducerEvent?)dbEvent); } - public void OnDeleteEvent(ClientApi.Event? dbEvent) + public void OnDeleteEvent(ReducerEventBase? dbEvent) { - OnDelete?.Invoke((T)this, (ReducerEvent?)dbEvent?.FunctionCall.CallInfo); + OnDelete?.Invoke((T)this, (ReducerEvent?)dbEvent); } } public interface IDatabaseTableWithPrimaryKey : IDatabaseTable { - void OnUpdateEvent(IDatabaseTableWithPrimaryKey newValue, ClientApi.Event? dbEvent); + void OnUpdateEvent(IDatabaseTableWithPrimaryKey newValue, ReducerEventBase? update); object GetPrimaryKeyValue(); } @@ -71,12 +72,12 @@ public abstract class DatabaseTableWithPrimaryKey : DatabaseTab { public abstract object GetPrimaryKeyValue(); - public delegate void UpdateEventHandler(T oldValue, T newValue, ReducerEvent? dbEvent); + public delegate void UpdateEventHandler(T oldValue, T newValue, ReducerEvent? update); public static event UpdateEventHandler? OnUpdate; - public void OnUpdateEvent(IDatabaseTableWithPrimaryKey newValue, ClientApi.Event? dbEvent) + public void OnUpdateEvent(IDatabaseTableWithPrimaryKey newValue, ReducerEventBase? dbEvent) { - OnUpdate?.Invoke((T)this, (T)newValue, (ReducerEvent?)dbEvent?.FunctionCall.CallInfo); + OnUpdate?.Invoke((T)this, (T)newValue, (ReducerEvent?)dbEvent); } } } diff --git a/sdks/csharp/src/Primitives.cs b/sdks/csharp/src/Primitives.cs new file mode 100644 index 00000000000..9466cca5711 --- /dev/null +++ b/sdks/csharp/src/Primitives.cs @@ -0,0 +1,83 @@ +using SpacetimeDB.BSATN; + +using System; +using System.IO; + +namespace SpacetimeDB +{ + + public struct I128 : IEquatable + { + public long hi; + public ulong lo; + + public I128(long hi, ulong lo) + { + this.hi = hi; + this.lo = lo; + } + + public readonly bool Equals(I128 x) => hi == x.hi && lo == x.lo; + + public override readonly bool Equals(object? o) => o is I128 x && Equals(x); + + public static bool operator ==(I128 a, I128 b) => a.Equals(b); + public static bool operator !=(I128 a, I128 b) => !a.Equals(b); + + public override readonly int GetHashCode() => hi.GetHashCode() ^ lo.GetHashCode(); + + public override readonly string ToString() => $"I128({hi},{lo})"; + + public readonly struct BSATN : IReadWrite + { + public I128 Read(BinaryReader reader) => new(reader.ReadInt64(), reader.ReadUInt64()); + + public void Write(BinaryWriter writer, I128 value) + { + writer.Write(value.hi); + writer.Write(value.lo); + } + + public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => + new AlgebraicType.Builtin(new BuiltinType.I128(new Unit())); + } + } + + public struct U128 : IEquatable + { + public ulong hi; + public ulong lo; + + public U128(ulong hi, ulong lo) + { + this.lo = lo; + this.hi = hi; + } + + public readonly bool Equals(U128 x) => hi == x.hi && lo == x.lo; + + public override readonly bool Equals(object? o) => o is U128 x && Equals(x); + + public static bool operator ==(U128 a, U128 b) => a.Equals(b); + public static bool operator !=(U128 a, U128 b) => !a.Equals(b); + + public override readonly int GetHashCode() => hi.GetHashCode() ^ lo.GetHashCode(); + + public override readonly string ToString() => $"U128({hi},{lo})"; + + public readonly struct BSATN : IReadWrite + { + public U128 Read(BinaryReader reader) => new(reader.ReadUInt64(), reader.ReadUInt64()); + + public void Write(BinaryWriter writer, U128 value) + { + writer.Write(value.hi); + writer.Write(value.lo); + } + + public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => + new AlgebraicType.Builtin(new BuiltinType.U128(new Unit())); + } + } + +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs new file mode 100644 index 00000000000..0d065d40658 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class CallReducer + { + [DataMember(Name = "reducer")] + public string Reducer = ""; + + [DataMember(Name = "args")] + public SpacetimeDB.ClientApi.EncodedValue Args = null!; + + [DataMember(Name = "request_id")] + public uint RequestId; + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs new file mode 100644 index 00000000000..4badf680709 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs @@ -0,0 +1,17 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record ClientMessage : SpacetimeDB.TaggedEnum<( + SpacetimeDB.ClientApi.CallReducer CallReducer, + SpacetimeDB.ClientApi.Subscribe Subscribe, + SpacetimeDB.ClientApi.OneOffQuery OneOffQuery + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs new file mode 100644 index 00000000000..0cf2567e4d9 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs @@ -0,0 +1,22 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class DatabaseUpdate + { + [DataMember(Name = "tables")] + public System.Collections.Generic.List Tables = new(); + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs new file mode 100644 index 00000000000..16793ca5a30 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs @@ -0,0 +1,17 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record EncodedValue : SpacetimeDB.TaggedEnum<( + byte[] Binary, + string Text + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs new file mode 100644 index 00000000000..7cd07b36fbe --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs @@ -0,0 +1,22 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class EnergyQuanta + { + [DataMember(Name = "quanta")] + public U128 Quanta; + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs new file mode 100644 index 00000000000..b1bbd183e20 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class IdentityToken + { + [DataMember(Name = "identity")] + public SpacetimeDB.Identity Identity = new(); + + [DataMember(Name = "token")] + public string Token = ""; + + [DataMember(Name = "address")] + public SpacetimeDB.Address Address = new(); + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs new file mode 100644 index 00000000000..ed704238c7f --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class InitialSubscription + { + [DataMember(Name = "database_update")] + public SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate = new(); + + [DataMember(Name = "request_id")] + public uint RequestId; + + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs new file mode 100644 index 00000000000..c4625fe5450 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs @@ -0,0 +1,25 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class OneOffQuery + { + [DataMember(Name = "message_id")] + public byte[] MessageId = Array.Empty(); + + [DataMember(Name = "query_string")] + public string QueryString = ""; + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs new file mode 100644 index 00000000000..4e98289fca6 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs @@ -0,0 +1,31 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class OneOffQueryResponse + { + [DataMember(Name = "message_id")] + public byte[] MessageId = Array.Empty(); + + [DataMember(Name = "error")] + public string? Error; + + [DataMember(Name = "tables")] + public List Tables = new(); + + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs new file mode 100644 index 00000000000..84fa81bf6d2 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs @@ -0,0 +1,25 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class OneOffTable + { + [DataMember(Name = "table_name")] + public string TableName = ""; + + [DataMember(Name = "rows")] + public List Rows = new(); + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs new file mode 100644 index 00000000000..86a67416429 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs @@ -0,0 +1,31 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class ReducerCallInfo + { + [DataMember(Name = "reducer_name")] + public string ReducerName = ""; + + [DataMember(Name = "reducer_id")] + public uint ReducerId; + + [DataMember(Name = "args")] + public SpacetimeDB.ClientApi.EncodedValue Args = null!; + + [DataMember(Name = "request_id")] + public uint RequestId; + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs new file mode 100644 index 00000000000..7f4bf714e9a --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs @@ -0,0 +1,18 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record ServerMessage : SpacetimeDB.TaggedEnum<( + SpacetimeDB.ClientApi.InitialSubscription InitialSubscription, + SpacetimeDB.ClientApi.TransactionUpdate TransactionUpdate, + SpacetimeDB.ClientApi.IdentityToken IdentityToken, + SpacetimeDB.ClientApi.OneOffQueryResponse OneOffQueryResponse + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs new file mode 100644 index 00000000000..e844a34799c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs @@ -0,0 +1,25 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class Subscribe + { + [DataMember(Name = "query_strings")] + public System.Collections.Generic.List QueryStrings = new(); + + [DataMember(Name = "request_id")] + public uint RequestId; + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs new file mode 100644 index 00000000000..63400ee6a5d --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs @@ -0,0 +1,31 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [DataContract] + [SpacetimeDB.Type] + public partial class TableUpdate + { + [DataMember(Name = "table_id")] + public uint TableId; + + [DataMember(Name = "table_name")] + public string TableName = ""; + + [DataMember(Name = "deletes")] + public List Deletes = new(); + + [DataMember(Name = "inserts")] + public List Inserts = new(); + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs new file mode 100644 index 00000000000..4dd2535c26b --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs @@ -0,0 +1,23 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class Timestamp + { + [DataMember(Name = "microseconds")] + public ulong Microseconds; + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs new file mode 100644 index 00000000000..5861e9eef30 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs @@ -0,0 +1,40 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class TransactionUpdate + { + [DataMember(Name = "status")] + public SpacetimeDB.ClientApi.UpdateStatus Status = null!; + + [DataMember(Name = "timestamp")] + public SpacetimeDB.ClientApi.Timestamp Timestamp = new(); + + [DataMember(Name = "caller_identity")] + public SpacetimeDB.Identity CallerIdentity = new(); + + [DataMember(Name = "caller_address")] + public SpacetimeDB.Address CallerAddress = new(); + + [DataMember(Name = "reducer_call")] + public SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall = new(); + + [DataMember(Name = "energy_quanta_used")] + public SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed = new(); + + [DataMember(Name = "host_execution_duration_micros")] + public ulong HostExecutionDurationMicros; + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs new file mode 100644 index 00000000000..b788434e96c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs @@ -0,0 +1,18 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record UpdateStatus : SpacetimeDB.TaggedEnum<( + SpacetimeDB.ClientApi.DatabaseUpdate Committed, + string Failed, + SpacetimeDB.Unit OutOfEnergy + )>; +} diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index d78f1185023..0640271b27e 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -7,11 +7,9 @@ using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; -using ClientApi; using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; using Thread = System.Threading.Thread; -using Google.Protobuf; -using Event = ClientApi.Event; namespace SpacetimeDB { @@ -80,7 +78,7 @@ struct DbOp /// /// Invoked when an event message is received or at the end of a transaction update. /// - public event Action? onEvent; + public event Action? onEvent; public readonly Address clientAddress = Address.Random(); public Identity clientIdentity { get; private set; } @@ -89,7 +87,7 @@ struct DbOp private bool connectionClosed; protected readonly ClientCache clientDB = new(); - protected abstract ReducerEvent ReducerEventFromDbEvent(ClientApi.Event dbEvent); + protected abstract ReducerEvent ReducerEventFromDbEvent(TransactionUpdate dbEvent); private readonly Dictionary> waitingOneOffQueries = new(); @@ -99,13 +97,13 @@ struct DbOp protected SpacetimeDBClientBase() { - var options = new SpacetimeDB.ConnectOptions + var options = new ConnectOptions { //v1.bin.spacetimedb //v1.text.spacetimedb Protocol = "v1.bin.spacetimedb", }; - webSocket = new SpacetimeDB.WebSocket(options); + webSocket = new WebSocket(options); webSocket.OnMessage += OnMessageReceived; webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); webSocket.OnConnect += () => onConnect?.Invoke(); @@ -124,15 +122,16 @@ struct UnprocessedMessage struct ProcessedMessage { - public Message message; + public ServerMessage message; public List dbOps; public DateTime timestamp; + public ReducerEvent? reducerEvent; } struct PreProcessedMessage { public ProcessedMessage processed; - public Dictionary>? subscriptionInserts; + public Dictionary>? subscriptionInserts; } private readonly BlockingCollection _messageQueue = @@ -146,21 +145,27 @@ struct PreProcessedMessage private readonly CancellationTokenSource _preProcessCancellationTokenSource = new(); private CancellationToken _preProcessCancellationToken => _preProcessCancellationTokenSource.Token; + static DbValue Decode(ClientCache.ITableCache table, EncodedValue value) => value switch + { + EncodedValue.Binary(var bin) => new DbValue(table.DecodeValue(bin), bin), + EncodedValue.Text(var text) => throw new InvalidOperationException("JavaScript messages aren't supported."), + _ => throw new InvalidOperationException(), + }; + void PreProcessMessages() { - while (!isClosing) + try { - try + while (!isClosing) { var message = _messageQueue.Take(_preProcessCancellationToken); var preprocessedMessage = PreProcessMessage(message); _preProcessedNetworkMessages.Add(preprocessedMessage, _preProcessCancellationToken); } - catch (OperationCanceledException) - { - // Normal shutdown - return; - } + } + catch (OperationCanceledException) + { + return; // Normal shutdown } PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) @@ -168,7 +173,10 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) var dbOps = new List(); using var compressedStream = new MemoryStream(unprocessed.bytes); using var decompressedStream = new BrotliStream(compressedStream, CompressionMode.Decompress); - var message = Message.Parser.ParseFrom(decompressedStream); + using var binaryReader = new BinaryReader(decompressedStream); + var message = new ServerMessage.BSATN().Read(binaryReader); + + ReducerEvent? reducerEvent = null; // This is all of the inserts Dictionary>? subscriptionInserts = null; @@ -188,10 +196,11 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) switch (message) { - case { TypeCase: Message.TypeOneofCase.SubscriptionUpdate, SubscriptionUpdate: var subscriptionUpdate }: - subscriptionInserts = new(capacity: subscriptionUpdate.TableUpdates.Sum(a => a.TableRowOperations.Count)); + case ServerMessage.InitialSubscription(var initialSubscription): + subscriptionInserts = new(capacity: initialSubscription.DatabaseUpdate.Tables.Sum(a => a.Inserts.Count)); + // First apply all of the state - foreach (var update in subscriptionUpdate.TableUpdates) + foreach (var update in initialSubscription.DatabaseUpdate.Tables) { var tableName = update.TableName; var table = clientDB.GetTable(tableName); @@ -201,122 +210,160 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) continue; } - var hashSet = GetInsertHashSet(table.ClientTableType, subscriptionUpdate.TableUpdates.Count); - - foreach (var row in update.TableRowOperations) + if (update.Deletes.Count != 0) { - var rowBytes = row.Row.ToByteArray(); + Logger.LogWarning("Non-insert during a subscription update!"); + } - if (row.Op != TableRowOperation.Types.OperationType.Insert) - { - Logger.LogWarning("Non-insert during a subscription update!"); - continue; - } + var hashSet = GetInsertHashSet(table.ClientTableType, initialSubscription.DatabaseUpdate.Tables.Count); - if (!hashSet.Add(rowBytes)) + foreach (var row in update.Inserts) + { + switch (row) { - // Ignore duplicate inserts in the same subscription update. - continue; - } + case EncodedValue.Binary(var bin): + if (!hashSet.Add(bin)) + { + // Ignore duplicate inserts in the same subscription update. + continue; + } + var obj = table.DecodeValue(bin); + var op = new DbOp + { + table = table, + insert = new(obj, bin), + }; - var obj = table.DecodeValue(row.Row); - var op = new DbOp - { - table = table, - insert = new(obj, rowBytes), - }; + dbOps.Add(op); + break; - dbOps.Add(op); + case EncodedValue.Text(var txt): + Logger.LogWarning("JavaScript messages are unsupported."); + break; + } } } break; - case { TypeCase: Message.TypeOneofCase.TransactionUpdate, TransactionUpdate: var transactionUpdate }: - // First apply all of the state - foreach (var update in transactionUpdate.SubscriptionUpdate.TableUpdates) + case ServerMessage.TransactionUpdate(var transactionUpdate): + switch (transactionUpdate.Status) { - var tableName = update.TableName; - var table = clientDB.GetTable(tableName); - if (table == null) - { - Logger.LogError($"Unknown table name: {tableName}"); - continue; - } - - foreach (var row in update.TableRowOperations) - { - var rowBytes = row.Row.ToByteArray(); - - var obj = table.DecodeValue(row.Row); - - var op = new DbOp { table = table }; - - var dbValue = new DbValue(obj, rowBytes); - - if (row.Op == TableRowOperation.Types.OperationType.Insert) - { - op.insert = dbValue; - } - else - { - op.delete = dbValue; - } + case UpdateStatus.Committed(var committed): + primaryKeyChanges = new(); - if (obj is IDatabaseTableWithPrimaryKey objWithPk) + // First apply all of the state + foreach (var update in committed.Tables) { - // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, objWithPk.GetPrimaryKeyValue()); + var tableName = update.TableName; + var table = clientDB.GetTable(tableName); + if (table == null) + { + Logger.LogError($"Unknown table name: {tableName}"); + continue; + } - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) + foreach (var row in update.Inserts) { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) + var op = new DbOp { table = table, insert = Decode(table, row) }; + + if (op.insert.Value.value is IDatabaseTableWithPrimaryKey objWithPk) { - Logger.LogWarning($"Update with the same primary key was applied multiple times! tableName={tableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, objWithPk.GetPrimaryKeyValue()); + + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) + { + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) + { + Logger.LogWarning($"Update with the same primary key was applied multiple times! tableName={tableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. + continue; + } + + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + op = new DbOp + { + table = insertOp.table, + delete = deleteOp.delete, + insert = insertOp.insert, + }; + } + primaryKeyChanges[key] = op; + } + else + { + dbOps.Add(op); } - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + } - op = new DbOp + foreach (var row in update.Deletes) + { + var op = new DbOp { table = table, delete = Decode(table, row) }; + + if (op.delete.Value.value is IDatabaseTableWithPrimaryKey objWithPk) { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, objWithPk.GetPrimaryKeyValue()); + + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) + { + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) + { + Logger.LogWarning($"Update with the same primary key was applied multiple times! tableName={tableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. + continue; + } + + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + op = new DbOp + { + table = insertOp.table, + delete = deleteOp.delete, + insert = insertOp.insert, + }; + } + primaryKeyChanges[key] = op; + } + else + { + dbOps.Add(op); + } } + } + + // Combine primary key updates and non-primary key updates + dbOps.AddRange(primaryKeyChanges.Values); - primaryKeyChanges[key] = op; + // Convert the generic event arguments in to a domain specific event object + try + { + reducerEvent = ReducerEventFromDbEvent(transactionUpdate); } - else + catch (Exception e) { - dbOps.Add(op); + Logger.LogException(e); } - } - } - - // Combine primary key updates and non-primary key updates - dbOps.AddRange(primaryKeyChanges.Values); - - // Convert the generic event arguments in to a domain specific event object, this gets fed back into - // the message.TransactionUpdate.Event.FunctionCall.CallInfo field. - var dbEvent = message.TransactionUpdate.Event; - try - { - dbEvent.FunctionCall.CallInfo = ReducerEventFromDbEvent(dbEvent); - } - catch (Exception e) - { - Logger.LogException(e); + break; + case UpdateStatus.Failed(var failed): + break; + case UpdateStatus.OutOfEnergy(var outOfEnergy): + Logger.LogWarning("Failed to execute reducer: out of energy."); + break; + default: + throw new InvalidOperationException(); } - break; - case { TypeCase: Message.TypeOneofCase.OneOffQueryResponse, OneOffQueryResponse: var resp }: + case ServerMessage.IdentityToken(var identityToken): + break; + case ServerMessage.OneOffQueryResponse(var resp): /// This case does NOT produce a list of DBOps, because it should not modify the client cache state! - var messageId = new Guid(resp.MessageId.Span); + var messageId = new Guid(resp.MessageId); if (!waitingOneOffQueries.Remove(messageId, out var resultSource)) { @@ -326,13 +373,14 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) resultSource.SetResult(resp); break; + default: + throw new InvalidOperationException(); } - // Logger.LogWarning($"Total Updates preprocessed: {totalUpdateCount}"); return new PreProcessedMessage { - processed = new ProcessedMessage { message = message, dbOps = dbOps, timestamp = unprocessed.timestamp }, + processed = new ProcessedMessage { message = message, dbOps = dbOps, timestamp = unprocessed.timestamp, reducerEvent = reducerEvent }, subscriptionInserts = subscriptionInserts, }; } @@ -414,7 +462,7 @@ public void Connect(string? token, string uri, string addressOrName) } - private void OnMessageProcessCompleteUpdate(Event? transactionEvent, List dbOps) + private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List dbOps) { // First trigger OnBeforeDelete foreach (var update in dbOps) @@ -423,7 +471,7 @@ private void OnMessageProcessCompleteUpdate(Event? transactionEvent, List { try { - oldValue.OnBeforeDeleteEvent(transactionEvent); + oldValue.OnBeforeDeleteEvent(dbEvent!); } catch (Exception e) { @@ -477,16 +525,16 @@ private void OnMessageProcessCompleteUpdate(Event? transactionEvent, List // If we matched an update, these values must have primary keys. var newValue_ = (IDatabaseTableWithPrimaryKey)newValue; var oldValue_ = (IDatabaseTableWithPrimaryKey)oldValue; - oldValue_.OnUpdateEvent(newValue_, transactionEvent); + oldValue_.OnUpdateEvent(newValue_, dbEvent); break; } case { insert: { value: var newValue } }: - newValue.OnInsertEvent(transactionEvent); + newValue.OnInsertEvent(dbEvent); break; case { delete: { value: var oldValue } }: - oldValue.OnDeleteEvent(transactionEvent); + oldValue.OnDeleteEvent(dbEvent); break; } } @@ -506,10 +554,10 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) switch (message) { - case { TypeCase: Message.TypeOneofCase.SubscriptionUpdate, SubscriptionUpdate: var subscriptionUpdate }: + case ServerMessage.InitialSubscription(var initialSubscription): onBeforeSubscriptionApplied?.Invoke(); - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={message.TypeCase}"); - stats.SubscriptionRequestTracker.FinishTrackingRequest(subscriptionUpdate.RequestId); + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.InitialSubscription)}"); + stats.SubscriptionRequestTracker.FinishTrackingRequest(initialSubscription.RequestId); OnMessageProcessCompleteUpdate(null, dbOps); try { @@ -520,33 +568,32 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) Logger.LogException(e); } break; - case { TypeCase: Message.TypeOneofCase.TransactionUpdate, TransactionUpdate: var transactionUpdate }: - var transactionEvent = transactionUpdate.Event; - var reducer = transactionEvent.FunctionCall.Reducer; - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={message.TypeCase},reducer={reducer}"); - var hostDuration = TimeSpan.FromMilliseconds(transactionEvent.HostExecutionDurationMicros / 1000.0d); + case ServerMessage.TransactionUpdate(var transactionUpdate): + var reducer = transactionUpdate.ReducerCall.ReducerName; + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdate)},reducer={reducer}"); + var hostDuration = TimeSpan.FromMilliseconds(transactionUpdate.HostExecutionDurationMicros / 1000.0d); stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); - var callerIdentity = Identity.From(transactionEvent.CallerIdentity.ToByteArray()); + var callerIdentity = transactionUpdate.CallerIdentity; if (callerIdentity == clientIdentity) { // This was a request that we initiated - var requestId = transactionUpdate.SubscriptionUpdate.RequestId; + var requestId = transactionUpdate.ReducerCall.RequestId; if (!stats.ReducerRequestTracker.FinishTrackingRequest(requestId)) { Logger.LogWarning($"Failed to finish tracking reducer request: {requestId}"); } } - OnMessageProcessCompleteUpdate(transactionEvent, dbOps); + OnMessageProcessCompleteUpdate(processed.reducerEvent, dbOps); try { - onEvent?.Invoke(transactionEvent); + onEvent?.Invoke(message); } catch (Exception e) { Logger.LogException(e); } - if (transactionEvent.FunctionCall.CallInfo is not { } reducerEvent) + if (processed.reducerEvent is not { } reducerEvent) { // If we are here, an error about unknown reducer should have already been logged, so nothing to do. break; @@ -562,11 +609,11 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) Logger.LogException(e); } - if (!reducerFound && transactionEvent.Status == Event.Types.Status.Failed) + if (!reducerFound && transactionUpdate.Status is UpdateStatus.Failed(var failed)) { try { - onUnhandledReducerError?.Invoke((ReducerEvent)reducerEvent); + onUnhandledReducerError?.Invoke(reducerEvent); } catch (Exception e) { @@ -574,11 +621,11 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } } break; - case { TypeCase: Message.TypeOneofCase.IdentityToken, IdentityToken: var identityToken }: + case ServerMessage.IdentityToken(var identityToken): try { - clientIdentity = Identity.From(identityToken.Identity.ToByteArray()); - var address = Address.From(identityToken.Address.ToByteArray()) ?? throw new Exception("Received zero address"); + clientIdentity = identityToken.Identity; + var address = identityToken.Address; onIdentityReceived?.Invoke(identityToken.Token, clientIdentity, address); } catch (Exception e) @@ -586,10 +633,10 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) Logger.LogException(e); } break; - case { TypeCase: Message.TypeOneofCase.Event, Event: var event_ }: + case ServerMessage.OneOffQueryResponse(var _): try { - onEvent?.Invoke(event_); + onEvent?.Invoke(message); } catch (Exception e) { @@ -597,6 +644,8 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } break; + default: + throw new InvalidOperationException(); } } @@ -613,15 +662,18 @@ public void InternalCallReducer(T args) return; } - webSocket.Send(new Message - { - FunctionCall = new FunctionCall + var o = new MemoryStream(); + var bw = new BinaryWriter(o); + args.WriteFields(bw); + + webSocket.Send(new ClientMessage.CallReducer( + new CallReducer { RequestId = stats.ReducerRequestTracker.StartTrackingRequest(args.ReducerName), Reducer = args.ReducerName, - ArgBytes = args.ToProtoBytes(), - }, - }); + Args = new EncodedValue.Binary(o.ToArray()) + } + )); } public void Subscribe(List queries) @@ -632,12 +684,12 @@ public void Subscribe(List queries) return; } - var request = new ClientApi.Subscribe + var request = new Subscribe { RequestId = stats.SubscriptionRequestTracker.StartTrackingRequest(), }; request.QueryStrings.AddRange(queries); - webSocket.Send(new Message { Subscribe = request }); + webSocket.Send(new ClientMessage.Subscribe(request)); } /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("WHERE sender = \"bob\""); @@ -654,14 +706,11 @@ public async Task OneOffQuery(string query) string queryString = $"SELECT * FROM {type.Name} {query}"; var requestId = stats.OneOffRequestTracker.StartTrackingRequest(); - webSocket.Send(new Message + webSocket.Send(new ClientMessage.OneOffQuery(new OneOffQuery { - OneOffQuery = new ClientApi.OneOffQuery - { - MessageId = UnsafeByteOperations.UnsafeWrap(messageId.ToByteArray()), - QueryString = queryString, - } - }); + MessageId = messageId.ToByteArray(), + QueryString = queryString, + })); // Suspend for an arbitrary amount of time var result = await resultSource.Task; @@ -697,7 +746,7 @@ T[] LogAndThrow(string error) return LogAndThrow($"Mismatched result type, expected {type} but got {resultTable.TableName}"); } - return resultTable.Row.Select(row => BSATNHelpers.FromProtoBytes(row)).ToArray(); + return resultTable.Rows.Select(BSATNHelpers.Decode).ToArray(); } public bool IsConnected() => webSocket.IsConnected; diff --git a/sdks/csharp/src/Stubs.cs b/sdks/csharp/src/Stubs.cs index 9e43197a230..f9ba62020d3 100644 --- a/sdks/csharp/src/Stubs.cs +++ b/sdks/csharp/src/Stubs.cs @@ -1,3 +1,5 @@ +using SpacetimeDB.ClientApi; + namespace SpacetimeDB { public interface IReducerArgsBase : BSATN.IStructuralReadWrite @@ -8,23 +10,23 @@ public interface IReducerArgsBase : BSATN.IStructuralReadWrite public abstract class ReducerEventBase { public ulong Timestamp { get; } - public SpacetimeDB.Identity? Identity { get; } - public SpacetimeDB.Address? CallerAddress { get; } + public Identity? Identity { get; } + public Address? CallerAddress { get; } public string? ErrMessage { get; } - public ClientApi.Event.Types.Status Status { get; } + public UpdateStatus? Status { get; } - public ReducerEventBase() - { - Status = ClientApi.Event.Types.Status.Committed; - } + public ReducerEventBase() { } - public ReducerEventBase(ClientApi.Event dbEvent) + public ReducerEventBase(TransactionUpdate update) { - Timestamp = dbEvent.Timestamp; - Identity = SpacetimeDB.Identity.From(dbEvent.CallerIdentity.ToByteArray()); - CallerAddress = Address.From(dbEvent.CallerAddress.ToByteArray()); - ErrMessage = dbEvent.Message; - Status = dbEvent.Status; + Timestamp = update.Timestamp.Microseconds; + Identity = update.CallerIdentity; + CallerAddress = update.CallerAddress; + Status = update.Status; + if (update.Status is UpdateStatus.Failed(var err)) + { + ErrMessage = err; + } } public abstract bool InvokeHandler(); diff --git a/sdks/csharp/src/Utils.cs b/sdks/csharp/src/Utils.cs index 52f6f8a21cf..8e58a1d6954 100644 --- a/sdks/csharp/src/Utils.cs +++ b/sdks/csharp/src/Utils.cs @@ -2,10 +2,10 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; -#if UNITY_5_3_OR_NEWER +#if !NET5_0_OR_GREATER namespace System.Runtime.CompilerServices { - public static class IsExternalInit {} + public static class IsExternalInit { } // https://stackoverflow.com/a/64749403/1484415 } #endif diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 8422b14605b..59e28484ea8 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -1,11 +1,13 @@ +using SpacetimeDB.ClientApi; + using System; using System.Collections.Concurrent; +using System.IO; using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; -using Google.Protobuf; namespace SpacetimeDB { @@ -147,7 +149,7 @@ public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure } private Task? senderTask; - private readonly ConcurrentQueue messageSendQueue = new(); + private readonly ConcurrentQueue messageSendQueue = new(); /// /// This sender guarantees that that messages are sent out in the order they are received. Our websocket @@ -155,11 +157,11 @@ public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure /// before we start another one. This function is also thread safe, just in case. /// /// The message to send - public void Send(ClientApi.Message message) + public void Send(ClientMessage message) { lock (messageSendQueue) { - messageSendQueue.Enqueue(message.ToByteArray()); + messageSendQueue.Enqueue(message); senderTask ??= Task.Run(ProcessSendQueue); } } @@ -171,7 +173,7 @@ private async Task ProcessSendQueue() { while (true) { - byte[]? message; + ClientMessage message; lock (messageSendQueue) { @@ -183,7 +185,10 @@ private async Task ProcessSendQueue() } } - await Ws!.SendAsync(message, WebSocketMessageType.Binary, true, CancellationToken.None); + var o = new MemoryStream(); + var w = new BinaryWriter(o); + new ClientMessage.BSATN().Write(w, message); + await Ws!.SendAsync(o.ToArray(), WebSocketMessageType.Binary, true, CancellationToken.None); } } catch (Exception e) diff --git a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt index 34d30c98eaf..12aa9234c77 100644 --- a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -18,16 +18,16 @@ } }, OnEvent: { - Timestamp: 1718487763059031, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: __identity_connected__, - ArgBytes: + status: {Scrubbed}, + timestamp: 1718487763059031, + caller_identity: {Scrubbed}, + caller_address: Guid_2, + reducer_call: { + reducer_name: __identity_connected__, + args: }, - Message: , - EnergyQuantaUsed: 1957615, - HostExecutionDurationMicros: 66, - CallerAddress: Guid_2 + energy_quanta_used: 1957615, + host_execution_duration_micros: 66 }, OnUpdateUser: { oldUser: { @@ -46,30 +46,21 @@ Timestamp: 1718487768057579, Identity: Identity_1, CallerAddress: Guid_1, - ErrMessage: + Status: {Scrubbed} } }, OnEvent: { - Timestamp: 1718487768057579, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: set_name, - ArgBytes: 0100000041, - RequestId: 1, - CallInfo: { - Args: { - Name: A - }, - Timestamp: 1718487768057579, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } + status: {Scrubbed}, + timestamp: 1718487768057579, + caller_identity: {Scrubbed}, + caller_address: Guid_1, + reducer_call: { + reducer_name: set_name, + args: AQAAAEE=, + request_id: 1 }, - Message: , - EnergyQuantaUsed: 4345615, - HostExecutionDurationMicros: 70, - CallerAddress: Guid_1 + energy_quanta_used: 4345615, + host_execution_duration_micros: 70 }, OnSetName: { Args: { @@ -78,7 +69,7 @@ Timestamp: 1718487768057579, Identity: Identity_1, CallerAddress: Guid_1, - ErrMessage: + Status: {Scrubbed} }, OnInsertMessage: { message: { @@ -93,30 +84,21 @@ Timestamp: 1718487775346381, Identity: Identity_2, CallerAddress: Guid_2, - ErrMessage: + Status: {Scrubbed} } }, OnEvent: { - Timestamp: 1718487775346381, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: send_message, - ArgBytes: 0900000048656C6C6F2C204121, - RequestId: 1, - CallInfo: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718487775346381, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } + status: {Scrubbed}, + timestamp: 1718487775346381, + caller_identity: {Scrubbed}, + caller_address: Guid_2, + reducer_call: { + reducer_name: send_message, + args: CQAAAEhlbGxvLCBBIQ==, + request_id: 1 }, - Message: , - EnergyQuantaUsed: 2779615, - HostExecutionDurationMicros: 57, - CallerAddress: Guid_2 + energy_quanta_used: 2779615, + host_execution_duration_micros: 57 }, OnSendMessage: { Args: { @@ -125,7 +107,7 @@ Timestamp: 1718487775346381, Identity: Identity_2, CallerAddress: Guid_2, - ErrMessage: + Status: {Scrubbed} }, OnUpdateUser: { oldUser: { @@ -144,30 +126,21 @@ Timestamp: 1718487777307855, Identity: Identity_2, CallerAddress: Guid_2, - ErrMessage: + Status: {Scrubbed} } }, OnEvent: { - Timestamp: 1718487777307855, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: set_name, - ArgBytes: 0100000042, - RequestId: 2, - CallInfo: { - Args: { - Name: B - }, - Timestamp: 1718487777307855, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } + status: {Scrubbed}, + timestamp: 1718487777307855, + caller_identity: {Scrubbed}, + caller_address: Guid_2, + reducer_call: { + reducer_name: set_name, + args: AQAAAEI=, + request_id: 2 }, - Message: , - EnergyQuantaUsed: 4268615, - HostExecutionDurationMicros: 98, - CallerAddress: Guid_2 + energy_quanta_used: 4268615, + host_execution_duration_micros: 98 }, OnSetName: { Args: { @@ -176,7 +149,7 @@ Timestamp: 1718487777307855, Identity: Identity_2, CallerAddress: Guid_2, - ErrMessage: + Status: {Scrubbed} }, OnInsertMessage: { message: { @@ -191,30 +164,21 @@ Timestamp: 1718487783175083, Identity: Identity_1, CallerAddress: Guid_1, - ErrMessage: + Status: {Scrubbed} } }, OnEvent: { - Timestamp: 1718487783175083, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: send_message, - ArgBytes: 0900000048656C6C6F2C204221, - RequestId: 2, - CallInfo: { - Args: { - Text: Hello, B! - }, - Timestamp: 1718487783175083, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } + status: {Scrubbed}, + timestamp: 1718487783175083, + caller_identity: {Scrubbed}, + caller_address: Guid_1, + reducer_call: { + reducer_name: send_message, + args: CQAAAEhlbGxvLCBCIQ==, + request_id: 2 }, - Message: , - EnergyQuantaUsed: 2677615, - HostExecutionDurationMicros: 40, - CallerAddress: Guid_1 + energy_quanta_used: 2677615, + host_execution_duration_micros: 40 }, OnSendMessage: { Args: { @@ -223,7 +187,7 @@ Timestamp: 1718487783175083, Identity: Identity_1, CallerAddress: Guid_1, - ErrMessage: + Status: {Scrubbed} }, OnInsertMessage: { message: { @@ -238,30 +202,21 @@ Timestamp: 1718487787645364, Identity: Identity_2, CallerAddress: Guid_2, - ErrMessage: + Status: {Scrubbed} } }, OnEvent: { - Timestamp: 1718487787645364, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: send_message, - ArgBytes: 08000000476F6F6462796521, - RequestId: 3, - CallInfo: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487787645364, - Identity: Identity_2, - CallerAddress: Guid_2, - ErrMessage: - } + status: {Scrubbed}, + timestamp: 1718487787645364, + caller_identity: {Scrubbed}, + caller_address: Guid_2, + reducer_call: { + reducer_name: send_message, + args: CAAAAEdvb2RieWUh, + request_id: 3 }, - Message: , - EnergyQuantaUsed: 2636615, - HostExecutionDurationMicros: 28, - CallerAddress: Guid_2 + energy_quanta_used: 2636615, + host_execution_duration_micros: 28 }, OnSendMessage: { Args: { @@ -270,7 +225,7 @@ Timestamp: 1718487787645364, Identity: Identity_2, CallerAddress: Guid_2, - ErrMessage: + Status: {Scrubbed} }, LogException: Unknown reducer __identity_disconnected__ (Parameter 'Reducer'), OnUpdateUser: { @@ -286,16 +241,16 @@ } }, OnEvent: { - Timestamp: 1718487791901504, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: __identity_disconnected__, - ArgBytes: + status: {Scrubbed}, + timestamp: 1718487791901504, + caller_identity: {Scrubbed}, + caller_address: Guid_2, + reducer_call: { + reducer_name: __identity_disconnected__, + args: }, - Message: , - EnergyQuantaUsed: 3595615, - HostExecutionDurationMicros: 75, - CallerAddress: Guid_2 + energy_quanta_used: 3595615, + host_execution_duration_micros: 75 }, OnInsertMessage: { message: { @@ -310,30 +265,21 @@ Timestamp: 1718487794937841, Identity: Identity_1, CallerAddress: Guid_1, - ErrMessage: + Status: {Scrubbed} } }, OnEvent: { - Timestamp: 1718487794937841, - CallerIdentity: {Scrubbed}, - FunctionCall: { - Reducer: send_message, - ArgBytes: 08000000476F6F6462796521, - RequestId: 3, - CallInfo: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487794937841, - Identity: Identity_1, - CallerAddress: Guid_1, - ErrMessage: - } + status: {Scrubbed}, + timestamp: 1718487794937841, + caller_identity: {Scrubbed}, + caller_address: Guid_1, + reducer_call: { + reducer_name: send_message, + args: CAAAAEdvb2RieWUh, + request_id: 3 }, - Message: , - EnergyQuantaUsed: 2636615, - HostExecutionDurationMicros: 34, - CallerAddress: Guid_1 + energy_quanta_used: 2636615, + host_execution_duration_micros: 34 }, OnSendMessage: { Args: { @@ -342,7 +288,7 @@ Timestamp: 1718487794937841, Identity: Identity_1, CallerAddress: Guid_1, - ErrMessage: + Status: {Scrubbed} } }, FinalSnapshot: { @@ -402,7 +348,7 @@ ParseMessageTracker: { sampleCount: 9, Min: type=TransactionUpdate,reducer=send_message, - Max: type=SubscriptionUpdate + Max: type=InitialSubscription } } } \ No newline at end of file diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs index c6eb2af4097..1569fc5b90e 100644 --- a/sdks/csharp/tests/SnapshotTests.cs +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -3,10 +3,13 @@ namespace SpacetimeDB.Tests; using System.IO.Compression; using System.Runtime.CompilerServices; using Argon; -using Google.Protobuf; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; using SpacetimeDB.Types; using Xunit; +using U128 = SpacetimeDB.U128; + public class SnapshotTests { class Events : List> @@ -30,6 +33,38 @@ public override void Write(VerifyJsonWriter writer, Events events) } } + class TimestampConverter : WriteOnlyJsonConverter + { + public override void Write(VerifyJsonWriter writer, Timestamp timestamp) + { + writer.WriteValue(timestamp.Microseconds); + } + } + + class EnergyQuantaConverter : WriteOnlyJsonConverter + { + public override void Write(VerifyJsonWriter writer, EnergyQuanta value) + { + Assert.Equal(0uL, value.Quanta.hi); + writer.WriteValue(value.Quanta.lo); + } + } + + class EncodedValueConverter : WriteOnlyJsonConverter + { + public override void Write(VerifyJsonWriter writer, EncodedValue value) + { + if (value is EncodedValue.Binary(var bytes)) + { + writer.WriteValue(bytes); + } + else + { + throw new InvalidOperationException(); + } + } + } + class TestLogger(Events events) : ISpacetimeDBLogger { public void Log(string message) @@ -53,39 +88,160 @@ public void LogException(Exception e) } } - class ByteStringReaderConverter : JsonConverter + private static ServerMessage.IdentityToken SampleId(string identity, string token, string address) => + new(new() + { + Identity = Identity.From(Convert.FromBase64String(identity)), + Token = token, + Address = Address.From(Convert.FromBase64String(address)) ?? throw new InvalidDataException("address") + }); + + private static ServerMessage.InitialSubscription SampleSubscriptionUpdate( + uint requestId, + ulong hostExecutionDuration, + List updates + ) => new(new() { - public override ByteString ReadJson( - JsonReader reader, - Type type, - ByteString? existingValue, - bool hasExisting, - JsonSerializer serializer - ) - { - var s = reader.StringValue; - try - { - return ByteString.FromBase64(s); - } - catch - { - return ByteString.CopyFromUtf8(s); - } + RequestId = requestId, + TotalHostExecutionDurationMicros = hostExecutionDuration, + DatabaseUpdate = new DatabaseUpdate + { + Tables = updates } + }); - public override void WriteJson( - JsonWriter writer, - ByteString value, - JsonSerializer serializer - ) + private static ServerMessage.TransactionUpdate SampleTransactionUpdate( + ulong timestamp, + string callerIdentity, + string callerAddress, + uint requestId, + string reducerName, + ulong energyQuantaUsed, + ulong hostExecutionDuration, + List updates, + EncodedValue? args + ) => new(new() + { + Timestamp = new Timestamp { Microseconds = timestamp }, + CallerIdentity = Identity.From(Convert.FromBase64String(callerIdentity)), + CallerAddress = Address.From(Convert.FromBase64String(callerAddress)) ?? throw new InvalidDataException("callerAddress"), + HostExecutionDurationMicros = hostExecutionDuration, + EnergyQuantaUsed = new() { - throw new NotImplementedException(); - } + Quanta = new U128(0, energyQuantaUsed), + }, + ReducerCall = new() + { + RequestId = requestId, + ReducerName = reducerName, + Args = args ?? new EncodedValue.Binary([]) + }, + Status = new UpdateStatus.Committed(new() + { + Tables = updates + }) + }); + + private static TableUpdate SampleUpdate( + uint tableId, + string tableName, + List inserts, + List deletes + ) => new() + { + TableId = tableId, + TableName = tableName, + Inserts = inserts, + Deletes = deletes + }; + + private static EncodedValue.Binary Encode(in T value) where T : IStructuralReadWrite + { + var o = new MemoryStream(); + var w = new BinaryWriter(o); + value.WriteFields(w); + return new EncodedValue.Binary(o.ToArray()); } - private static string GetTestDir([CallerFilePath] string testFilePath = "") => - Path.GetDirectoryName(testFilePath)!; + private static TableUpdate SampleUserInsert(string identity, string? name, bool online) => + SampleUpdate(4097, "User", [Encode(new User + { + Identity = Identity.From(Convert.FromBase64String(identity)), + Name = name, + Online = online + })], []); + + private static TableUpdate SampleUserUpdate(string identity, string? oldName, string? newName, bool oldOnline, bool newOnline) => + SampleUpdate(4097, "User", [Encode(new User + { + Identity = Identity.From(Convert.FromBase64String(identity)), + Name = newName, + Online = newOnline + })], [Encode(new User + { + Identity = Identity.From(Convert.FromBase64String(identity)), + Name = oldName, + Online = oldOnline + })]); + + private static TableUpdate SampleMessage(string identity, ulong sent, string text) => + SampleUpdate(4098, "Message", [Encode(new Message + { + Sender = Identity.From(Convert.FromBase64String(identity)), + Sent = sent, + Text = text + })], []); + + private static ServerMessage[] SampleDump() => [ + SampleId( + "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", + "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiI4ZjkwY2M5NGE5OTY4ZGY2ZDI5N2JhYTY2NTAzYTg5M2IxYzM0YjBiMDAyNjhhNTE0ODk4ZGQ5NTRiMGRhMjBiIiwiaWF0IjoxNzE4NDg3NjY4LCJleHAiOm51bGx9.PSn481bLRqtFwIh46nOXDY14X3GKbz8t4K4GmBmz50loU6xzeL7zDdCh1V2cmiQsoGq8Erxg0r_6b6Y5SqKoBA", + "Vd4dFzcEzhLHJ6uNL8VXFg==" + ), + SampleSubscriptionUpdate( + 1, 366, [SampleUserInsert("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true)] + ), + SampleTransactionUpdate( + 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "__identity_connected__", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], + null + ), + SampleTransactionUpdate( + 1718487768057579, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 1, "set_name", 4345615, 70, [SampleUserUpdate("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, "A", true, true)], + Encode(new SetNameArgsStruct { Name = "A" }) + ), + SampleTransactionUpdate( + 1718487775346381, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 1, "send_message", 2779615, 57, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487775346381, "Hello, A!")], + Encode(new SendMessageArgsStruct { Text = "Hello, A!" }) + ), + SampleTransactionUpdate( + 1718487777307855, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 2, "set_name", 4268615, 98, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, "B", true, true)], + Encode(new SetNameArgsStruct { Name = "B" }) + ), + SampleTransactionUpdate( + 1718487783175083, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 2, "send_message", 2677615, 40, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487783175083, "Hello, B!")], + Encode(new SendMessageArgsStruct { Text = "Hello, B!" }) + ), + SampleTransactionUpdate( + 1718487787645364, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 3, "send_message", 2636615, 28, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487787645364, "Goodbye!")], + Encode(new SendMessageArgsStruct { Text = "Goodbye!" }) + ), + SampleTransactionUpdate( + 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "__identity_disconnected__", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], + null + ), + SampleTransactionUpdate( + 1718487794937841, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 3, "send_message", 2636615, 34, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487794937841, "Goodbye!")], + Encode(new SendMessageArgsStruct { Text = "Goodbye!" }) + ), + ]; [Fact] public async Task VerifyAllTablesParsed() @@ -96,14 +252,7 @@ public async Task VerifyAllTablesParsed() var client = SpacetimeDBClient.instance; - var jsonSettings = new JsonSerializerSettings - { - Converters = [new ByteStringReaderConverter()] - }; - - // We store the dump in JSON-NL format for simplicity (it's just `ClientApi.Message.toString()`) and readability. - var sampleDumpParsed = File.ReadLines(Path.Combine(GetTestDir(), "sample-dump.jsonl")) - .Select(line => JsonConvert.DeserializeObject(line, jsonSettings)); + var sampleDumpParsed = SampleDump(); // But for proper testing we need to convert it back to raw binary messages as if it was received over network. var sampleDumpBinary = sampleDumpParsed.Select( @@ -112,32 +261,32 @@ public async Task VerifyAllTablesParsed() // Start tracking requests in the stats handler so that those request IDs can later be found. switch (message) { - case - { - TypeCase: ClientApi.Message.TypeOneofCase.SubscriptionUpdate, - SubscriptionUpdate: var subscriptionUpdate - }: + case ServerMessage.InitialSubscription(var _): client.stats.SubscriptionRequestTracker.StartTrackingRequest($"sample#{i}"); break; - case - { - TypeCase: ClientApi.Message.TypeOneofCase.TransactionUpdate, - TransactionUpdate: var transactionUpdate - }: + case ServerMessage.TransactionUpdate(var _): client.stats.ReducerRequestTracker.StartTrackingRequest($"sample#{i}"); break; } using var output = new MemoryStream(); using (var brotli = new BrotliStream(output, CompressionMode.Compress)) { - message.WriteTo(brotli); + using var w = new BinaryWriter(brotli); + new ServerMessage.BSATN().Write(w, message); } return output.ToArray(); } ); client.onBeforeSubscriptionApplied += () => events.Add("OnBeforeSubscriptionApplied"); - client.onEvent += (ev) => events.Add("OnEvent", ev); + client.onEvent += (ev) => events.Add("OnEvent", ev switch + { + ServerMessage.IdentityToken(var o) => o, + ServerMessage.InitialSubscription(var o) => o, + ServerMessage.TransactionUpdate(var o) => o, + ServerMessage.OneOffQueryResponse(var o) => o, + _ => throw new InvalidOperationException() + }); client.onIdentityReceived += (_authToken, identity, address) => events.Add("OnIdentityReceived", new { identity, address }); client.onSubscriptionApplied += () => events.Add("OnSubscriptionApplied"); @@ -192,7 +341,14 @@ await Verify( Stats = client.stats } ) - .AddExtraSettings(settings => settings.Converters.AddRange([new EventsConverter()])) - .ScrubMember(_ => _.CallerIdentity); + .AddExtraSettings(settings => settings.Converters.AddRange([ + new EventsConverter(), + new TimestampConverter(), + new EnergyQuantaConverter(), + new EncodedValueConverter() + ])) + .ScrubMember(x => x.CallerIdentity) + .ScrubMember(x => x.Status) + .ScrubMember(x => x.Status); } } diff --git a/sdks/csharp/tests/VerifyInit.cs b/sdks/csharp/tests/VerifyInit.cs index 985045537a2..bc75d5e5805 100644 --- a/sdks/csharp/tests/VerifyInit.cs +++ b/sdks/csharp/tests/VerifyInit.cs @@ -1,19 +1,10 @@ namespace SpacetimeDB.Tests; using System.Runtime.CompilerServices; -using Google.Protobuf; using SpacetimeDB.Types; static class VerifyInit { - class ByteStringConverter : WriteOnlyJsonConverter - { - public override void Write(VerifyJsonWriter writer, ByteString value) - { - writer.WriteValue(Convert.ToHexString(value.Span)); - } - } - // A converter that scrubs identity to a stable string. class IdentityConverter : WriteOnlyJsonConverter { @@ -84,7 +75,6 @@ public static void Init() VerifierSettings.AddExtraSettings(settings => settings.Converters.AddRange( [ - new ByteStringConverter(), new IdentityConverter(), new AddressConverter(), new NetworkRequestTrackerConverter() diff --git a/sdks/csharp/tests/sample-dump.jsonl b/sdks/csharp/tests/sample-dump.jsonl deleted file mode 100644 index 67032dc20d7..00000000000 --- a/sdks/csharp/tests/sample-dump.jsonl +++ /dev/null @@ -1,10 +0,0 @@ -{ "identityToken": { "identity": "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiI4ZjkwY2M5NGE5OTY4ZGY2ZDI5N2JhYTY2NTAzYTg5M2IxYzM0YjBiMDAyNjhhNTE0ODk4ZGQ5NTRiMGRhMjBiIiwiaWF0IjoxNzE4NDg3NjY4LCJleHAiOm51bGx9.PSn481bLRqtFwIh46nOXDY14X3GKbz8t4K4GmBmz50loU6xzeL7zDdCh1V2cmiQsoGq8Erxg0r_6b6Y5SqKoBA", "address": "Vd4dFzcEzhLHJ6uNL8VXFg==" } } -{ "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaILAQE=" } ] } ], "requestId": 1, "totalHostExecutionDurationMicros": "366" } } -{ "transactionUpdate": { "event": { "timestamp": "1718487763059031", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "__identity_connected__" }, "energyQuantaUsed": "1957615", "hostExecutionDurationMicros": "66", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAQE=" } ] } ] } } } -{ "transactionUpdate": { "event": { "timestamp": "1718487768057579", "callerIdentity": "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "functionCall": { "reducer": "set_name", "argBytes": "AQAAAEE=", "requestId": 1 }, "energyQuantaUsed": "4345615", "hostExecutionDurationMicros": "70", "callerAddress": "Vd4dFzcEzhLHJ6uNL8VXFg==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaILAQE=" }, { "op": "INSERT", "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaILAAEAAABBAQ==" } ] } ], "requestId": 1, "totalHostExecutionDurationMicros": "1239" } } } -{ "transactionUpdate": { "event": { "timestamp": "1718487775346381", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "send_message", "argBytes": "CQAAAEhlbGxvLCBBIQ==", "requestId": 1 }, "energyQuantaUsed": "2779615", "hostExecutionDurationMicros": "57", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4098, "tableName": "Message", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mzX5mnfQaBgAJAAAASGVsbG8sIEEh" } ] } ], "requestId": 1, "totalHostExecutionDurationMicros": "793" } } } -{ "transactionUpdate": { "event": { "timestamp": "1718487777307855", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "set_name", "argBytes": "AQAAAEI=", "requestId": 2 }, "energyQuantaUsed": "4268615", "hostExecutionDurationMicros": "98", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAQE=" }, { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAAEAAABCAQ==" } ] } ], "requestId": 2, "totalHostExecutionDurationMicros": "1317" } } } -{ "transactionUpdate": { "event": { "timestamp": "1718487783175083", "callerIdentity": "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "functionCall": { "reducer": "send_message", "argBytes": "CQAAAEhlbGxvLCBCIQ==", "requestId": 2 }, "energyQuantaUsed": "2677615", "hostExecutionDurationMicros": "40", "callerAddress": "Vd4dFzcEzhLHJ6uNL8VXFg==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4098, "tableName": "Message", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaILq/PdnfQaBgAJAAAASGVsbG8sIEIh" } ] } ], "requestId": 2, "totalHostExecutionDurationMicros": "676" } } } -{ "transactionUpdate": { "event": { "timestamp": "1718487787645364", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "send_message", "argBytes": "CAAAAEdvb2RieWUh", "requestId": 3 }, "energyQuantaUsed": "2636615", "hostExecutionDurationMicros": "28", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4098, "tableName": "Message", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mtCkinvQaBgAIAAAAR29vZGJ5ZSE=" } ] } ], "requestId": 3, "totalHostExecutionDurationMicros": "569" } } } -{ "transactionUpdate": { "event": { "timestamp": "1718487791901504", "callerIdentity": "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "functionCall": { "reducer": "__identity_disconnected__" }, "energyQuantaUsed": "3595615", "hostExecutionDurationMicros": "75", "callerAddress": "Kwmeu5riP20rvCTNbBipLA==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4097, "tableName": "User", "tableRowOperations": [ { "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAAEAAABCAQ==" }, { "op": "INSERT", "row": "IAAAAJdKsxtRj0bQtZsK/ueKvfLb9N9uYKMy3OnDc6uL686mAAEAAABCAA==" } ] } ] } } } -{ "transactionUpdate": { "event": { "timestamp": "1718487794937841", "callerIdentity": "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "functionCall": { "reducer": "send_message", "argBytes": "CAAAAEdvb2RieWUh", "requestId": 3 }, "energyQuantaUsed": "2636615", "hostExecutionDurationMicros": "34", "callerAddress": "Vd4dFzcEzhLHJ6uNL8VXFg==" }, "subscriptionUpdate": { "tableUpdates": [ { "tableId": 4098, "tableName": "Message", "tableRowOperations": [ { "op": "INSERT", "row": "IAAAAI+QzJSplo320pe6pmUDqJOxw0sLACaKUUiY3ZVLDaIL8W+RnvQaBgAIAAAAR29vZGJ5ZSE=" } ] } ], "requestId": 3, "totalHostExecutionDurationMicros": "1072" } } } From 706b945103296da9805a36b76b8178b42ecd35fd Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Fri, 12 Jul 2024 12:36:21 -0400 Subject: [PATCH 095/223] Revert breaking change in message preprocessing (#106) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/SpacetimeDBClient.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 0640271b27e..132d6724b9c 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -154,18 +154,18 @@ struct PreProcessedMessage void PreProcessMessages() { - try + while (!isClosing) { - while (!isClosing) + try { var message = _messageQueue.Take(_preProcessCancellationToken); var preprocessedMessage = PreProcessMessage(message); _preProcessedNetworkMessages.Add(preprocessedMessage, _preProcessCancellationToken); } - } - catch (OperationCanceledException) - { - return; // Normal shutdown + catch (OperationCanceledException) + { + return; // Normal shutdown + } } PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) From 5e065065b54618b260e35d90c83e2001e49f1b31 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Wed, 24 Jul 2024 20:46:07 +0000 Subject: [PATCH 096/223] CI - Use SpacetimeDB `master` when applicable (#108) ## Description of Changes Our CI now uses the packages from SpacetimeDB's `master` branch when applicable. ## Testing - [x] CI passes in test PR merging in the 0.11 upgrades: https://github.com/clockworklabs/spacetimedb-csharp-sdk/pull/109 --------- Co-authored-by: Zeke Foppa --- sdks/csharp/.github/workflows/dotnet.yml | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml index 1b93dfbe229..ad799182bb9 100644 --- a/sdks/csharp/.github/workflows/dotnet.yml +++ b/sdks/csharp/.github/workflows/dotnet.yml @@ -12,15 +12,49 @@ jobs: steps: - uses: actions/checkout@v4 + with: + path: spacetimedb-csharp-sdk - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: 7.0.x + - name: Checkout SpacetimeDB + uses: actions/checkout@v4 + with: + repository: clockworklabs/SpacetimeDB + path: SpacetimeDB + - name: Setup SpacetimeDB packages + working-directory: spacetimedb-csharp-sdk + run: | + ( cd ../SpacetimeDB/crates/bindings-csharp/BSATN.Runtime && dotnet pack ) + + # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository + # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if + # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. + # This means that (if version numbers match) we will test the local versions of the C# packages, even + # if they're not pushed to NuGet. + # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file, + # and https://tldp.org/LDP/abs/html/here-docs.html for more info on this bash feature. + cat >nuget.config < + + + + + + + + + EOF - name: Restore dependencies + working-directory: spacetimedb-csharp-sdk run: dotnet restore - name: Build everything + working-directory: spacetimedb-csharp-sdk run: dotnet build --no-restore -warnaserror - name: Run tests + working-directory: spacetimedb-csharp-sdk run: dotnet test --no-build - name: Verify formatting + working-directory: spacetimedb-csharp-sdk run: dotnet format --no-restore --verify-no-changes SpacetimeDB.ClientSDK.sln From 554df35b31b8de888663ea4ff2c1bcebccdee156 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 25 Jul 2024 17:18:45 +0100 Subject: [PATCH 097/223] 0.11 upgrades (#101) ## Description of Changes - Roslyn codegen won't need to be added as a separate dependency anymore. - ByteArrayComparer, Identity, and Address will now live in BSATN.Runtime so that they're reused between the client and module SDKs. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs - [x] https://github.com/clockworklabs/SpacetimeDB/pull/1440 - [ ] https://github.com/clockworklabs/SpacetimeDB/pull/1455 --------- Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 79 +++++++++---------- .../examples/quickstart/client/client.csproj | 1 - sdks/csharp/src/Address.cs | 61 -------------- sdks/csharp/src/ClientCache.cs | 1 + sdks/csharp/src/Identity.cs | 45 ----------- sdks/csharp/src/SpacetimeDBClient.cs | 3 +- sdks/csharp/src/Utils.cs | 61 +------------- sdks/csharp/tests/tests.csproj | 2 +- 8 files changed, 42 insertions(+), 211 deletions(-) delete mode 100644 sdks/csharp/src/Address.cs delete mode 100644 sdks/csharp/src/Identity.cs diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 51d95cd33b5..6600c39ef66 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -1,43 +1,36 @@ - - - - netstandard2.1 - 9 - disable - enable - True - SpacetimeDB.ClientSDK - SpacetimeDB SDK - jdetter - Clockwork Labs - SpacetimeDB - The SpacetimeDB SDK is a software development kit (SDK) designed to simplify the interaction with SpacetimeDB server modules. - 2023 - https://spacetimedb.com - logo.png - README.md - https://github.com/clockworklabs/spacetimedb-csharp-sdk - 0.10.0 - $(AssemblyVersion) - $(DefaultItemExcludes);examples/**;tests/** - - - - - - - - - - - - True - \ - - - True - \ - - - - + + + + netstandard2.1 + 9 + disable + enable + True + SpacetimeDB.ClientSDK + SpacetimeDB SDK + jdetter + Clockwork Labs + SpacetimeDB + The SpacetimeDB SDK is a software development kit (SDK) designed to simplify the interaction with SpacetimeDB server modules. + 2024 + https://spacetimedb.com + logo.png + README.md + https://github.com/clockworklabs/spacetimedb-csharp-sdk + 0.11.0 + $(AssemblyVersion) + $(DefaultItemExcludes);examples/**;tests/** + + + + + + + + + + + + + + diff --git a/sdks/csharp/examples/quickstart/client/client.csproj b/sdks/csharp/examples/quickstart/client/client.csproj index f5c7cde4fee..45e7e2664e8 100644 --- a/sdks/csharp/examples/quickstart/client/client.csproj +++ b/sdks/csharp/examples/quickstart/client/client.csproj @@ -11,7 +11,6 @@ - diff --git a/sdks/csharp/src/Address.cs b/sdks/csharp/src/Address.cs deleted file mode 100644 index ca4c3199309..00000000000 --- a/sdks/csharp/src/Address.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using SpacetimeDB.BSATN; - -namespace SpacetimeDB -{ - public readonly struct Address : IEquatable
    - { - public const int SIZE = 16; - - public readonly byte[] Bytes; - - private Address(byte[] bytes) => Bytes = bytes; - - public readonly struct BSATN : IReadWrite
    - { - public Address Read(BinaryReader reader) => - new(ByteArray.Instance.Read(reader)); - - public void Write(BinaryWriter writer, Address value) => - ByteArray.Instance.Write(writer, value.Bytes); - - public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.Product( - new AggregateElement[] - { - new("__address_bytes", ByteArray.Instance.GetAlgebraicType(registrar)) - } - ); - } - - public static Address? From(byte[] bytes) - { - if (bytes.All(b => b == 0)) - { - return null; - } - return new(bytes); - } - - public bool Equals(Address other) => ByteArrayComparer.Instance.Equals(Bytes, other.Bytes); - - public override bool Equals(object? o) => o is Address other && Equals(other); - - public static bool operator ==(Address a, Address b) => a.Equals(b); - public static bool operator !=(Address a, Address b) => !a.Equals(b); - - public static Address Random() - { - var random = new Random(); - var bytes = new byte[16]; - random.NextBytes(bytes); - return new(bytes); - } - - public override int GetHashCode() => ByteArrayComparer.Instance.GetHashCode(Bytes); - - public override string ToString() => ByteArrayComparer.ToHexString(Bytes); - } -} diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 719a6326048..45973df3354 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using SpacetimeDB.BSATN; +using SpacetimeDB.Internal; using SpacetimeDB.ClientApi; namespace SpacetimeDB diff --git a/sdks/csharp/src/Identity.cs b/sdks/csharp/src/Identity.cs deleted file mode 100644 index c0ad8d7676f..00000000000 --- a/sdks/csharp/src/Identity.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.IO; -using SpacetimeDB.BSATN; - -namespace SpacetimeDB -{ - public readonly struct Identity : IEquatable - { - - public const int SIZE = 32; - - public readonly byte[] Bytes; - - private Identity(byte[] bytes) => Bytes = bytes; - - public readonly struct BSATN : IReadWrite - { - public Identity Read(BinaryReader reader) => From(ByteArray.Instance.Read(reader)); - public void Write(BinaryWriter writer, Identity value) => ByteArray.Instance.Write(writer, value.Bytes); - - public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.Product( - new AggregateElement[] - { - new("__identity_bytes", ByteArray.Instance.GetAlgebraicType(registrar)) - } - ); - } - - public static Identity From(byte[] bytes) => - // TODO: should we validate length here? - new(bytes); - - public bool Equals(Identity other) => ByteArrayComparer.Instance.Equals(Bytes, other.Bytes); - - public override bool Equals(object? o) => o is Identity other && Equals(other); - - public static bool operator ==(Identity a, Identity b) => a.Equals(b); - public static bool operator !=(Identity a, Identity b) => !a.Equals(b); - - public override int GetHashCode() => ByteArrayComparer.Instance.GetHashCode(Bytes); - - public override string ToString() => ByteArrayComparer.ToHexString(Bytes); - } -} diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 132d6724b9c..89774b511c9 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using SpacetimeDB.BSATN; +using SpacetimeDB.Internal; using SpacetimeDB.ClientApi; using Thread = System.Threading.Thread; @@ -81,7 +82,7 @@ struct DbOp public event Action? onEvent; public readonly Address clientAddress = Address.Random(); - public Identity clientIdentity { get; private set; } + public Identity? clientIdentity { get; private set; } private SpacetimeDB.WebSocket webSocket; private bool connectionClosed; diff --git a/sdks/csharp/src/Utils.cs b/sdks/csharp/src/Utils.cs index 8e58a1d6954..8e25f20112b 100644 --- a/sdks/csharp/src/Utils.cs +++ b/sdks/csharp/src/Utils.cs @@ -1,63 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -#if !NET5_0_OR_GREATER +#if !NET5_0_OR_GREATER namespace System.Runtime.CompilerServices { - public static class IsExternalInit { } // https://stackoverflow.com/a/64749403/1484415 + internal static class IsExternalInit { } // https://stackoverflow.com/a/64749403/1484415 } #endif - -namespace SpacetimeDB -{ - // Note: this utility struct is used by an autogenerated C# code so it needs to be public. - public readonly struct ByteArrayComparer : IEqualityComparer - { - public static readonly ByteArrayComparer Instance = new(); - - public bool Equals(byte[]? left, byte[]? right) - { - if (ReferenceEquals(left, right)) - { - return true; - } - - if (left is null || right is null || left.Length != right.Length) - { - return false; - } - - return EqualsUnvectorized(left, right); - - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool EqualsUnvectorized(byte[] left, byte[] right) - { - for (int i = 0; i < left.Length; i++) - { - if (left[i] != right[i]) - { - return false; - } - } - - return true; - } - - public int GetHashCode(byte[] obj) - { - int hash = 17; - foreach (byte b in obj) - { - hash = hash * 31 + b; - } - return hash; - } - - // Same as `Convert.ToHexString`, but that method is not available in .NET Standard - // which we need to target for Unity support. - public static string ToHexString(byte[] bytes) => BitConverter.ToString(bytes).Replace("-", ""); - } -} diff --git a/sdks/csharp/tests/tests.csproj b/sdks/csharp/tests/tests.csproj index 30b5def6ee5..20dc5b0e6d1 100644 --- a/sdks/csharp/tests/tests.csproj +++ b/sdks/csharp/tests/tests.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + SpacetimeDB.Tests false true @@ -21,7 +22,6 @@ - From cd5f44b3161bb3faba1682c4034592e37d133534 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:40:03 +0000 Subject: [PATCH 098/223] CI - `push` events only trigger on pushes to `master` (#110) ## Description of Changes Currently, a push to a PR triggers our `dotnet` workflows twice: once for the `push` event, and once for the `pull_request` event. This PR brings the CI behavior in line with how SpacetimeDB does it. (Someday we should reduce the number of `pull_request` events that trigger this, but today is not that day). --------- Co-authored-by: Zeke Foppa --- sdks/csharp/.github/workflows/dotnet.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml index ad799182bb9..9733140e806 100644 --- a/sdks/csharp/.github/workflows/dotnet.yml +++ b/sdks/csharp/.github/workflows/dotnet.yml @@ -3,7 +3,10 @@ name: .NET build -on: [push, pull_request] +on: + push: + pull_request: + types: [opened, reopened] jobs: build: From 9fba1562ab3239a57472ff75f7e254cca51cd89e Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 29 Jul 2024 12:20:25 +0100 Subject: [PATCH 099/223] Minor BSATN simplifications (#111) ## Description of Changes Minor simplifications using BSATN helpers for Protobufectomy code. Also removed unnecessary usings and a pattern. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/ClientCache.cs | 1 - sdks/csharp/src/IDatabaseTable.cs | 1 - sdks/csharp/src/SpacetimeDBClient.cs | 8 ++------ sdks/csharp/src/WebSocket.cs | 9 ++++----- sdks/csharp/tests/SnapshotTests.cs | 2 -- 5 files changed, 6 insertions(+), 15 deletions(-) diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 45973df3354..ec0a7212c4e 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -4,7 +4,6 @@ using System.Linq; using SpacetimeDB.BSATN; using SpacetimeDB.Internal; -using SpacetimeDB.ClientApi; namespace SpacetimeDB { diff --git a/sdks/csharp/src/IDatabaseTable.cs b/sdks/csharp/src/IDatabaseTable.cs index 5e78f922c39..a028771a794 100644 --- a/sdks/csharp/src/IDatabaseTable.cs +++ b/sdks/csharp/src/IDatabaseTable.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using SpacetimeDB.BSATN; -using SpacetimeDB.ClientApi; namespace SpacetimeDB { diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 89774b511c9..e0a9daa4f70 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -634,7 +634,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) Logger.LogException(e); } break; - case ServerMessage.OneOffQueryResponse(var _): + case ServerMessage.OneOffQueryResponse: try { onEvent?.Invoke(message); @@ -663,16 +663,12 @@ public void InternalCallReducer(T args) return; } - var o = new MemoryStream(); - var bw = new BinaryWriter(o); - args.WriteFields(bw); - webSocket.Send(new ClientMessage.CallReducer( new CallReducer { RequestId = stats.ReducerRequestTracker.StartTrackingRequest(args.ReducerName), Reducer = args.ReducerName, - Args = new EncodedValue.Binary(o.ToArray()) + Args = new EncodedValue.Binary(IStructuralReadWrite.ToBytes(args)) } )); } diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 59e28484ea8..9944552888f 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -1,8 +1,8 @@ +using SpacetimeDB.BSATN; using SpacetimeDB.ClientApi; using System; using System.Collections.Concurrent; -using System.IO; using System.Linq; using System.Net.WebSockets; using System.Text; @@ -185,10 +185,9 @@ private async Task ProcessSendQueue() } } - var o = new MemoryStream(); - var w = new BinaryWriter(o); - new ClientMessage.BSATN().Write(w, message); - await Ws!.SendAsync(o.ToArray(), WebSocketMessageType.Binary, true, CancellationToken.None); + var messageBSATN = new ClientMessage.BSATN(); + var encodedMessage = IStructuralReadWrite.ToBytes(messageBSATN, message); + await Ws!.SendAsync(encodedMessage, WebSocketMessageType.Binary, true, CancellationToken.None); } } catch (Exception e) diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs index 1569fc5b90e..8f722b3cfe0 100644 --- a/sdks/csharp/tests/SnapshotTests.cs +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -1,8 +1,6 @@ namespace SpacetimeDB.Tests; using System.IO.Compression; -using System.Runtime.CompilerServices; -using Argon; using SpacetimeDB.BSATN; using SpacetimeDB.ClientApi; using SpacetimeDB.Types; From 5394c639cdde52f7d4d0faa32b68c7b77de60c09 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 6 Aug 2024 21:06:17 +0200 Subject: [PATCH 100/223] Don't use BuiltinType.I/U128, use AlgebraicType.I/U128 (#116) ## Description of Changes Required to make "SDK Tests" pass in https://github.com/clockworklabs/SpacetimeDB/pull/1559. ## API Not breaking. ## Requires SpacetimeDB PRs - https://github.com/clockworklabs/SpacetimeDB/pull/1559 --------- Co-authored-by: Zeke Foppa --- sdks/csharp/src/Primitives.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/src/Primitives.cs b/sdks/csharp/src/Primitives.cs index 9466cca5711..93ba5e982ae 100644 --- a/sdks/csharp/src/Primitives.cs +++ b/sdks/csharp/src/Primitives.cs @@ -39,7 +39,7 @@ public void Write(BinaryWriter writer, I128 value) } public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.Builtin(new BuiltinType.I128(new Unit())); + new AlgebraicType.I128(new Unit()); } } @@ -76,7 +76,7 @@ public void Write(BinaryWriter writer, U128 value) } public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.Builtin(new BuiltinType.U128(new Unit())); + new AlgebraicType.U128(new Unit()); } } From 655c2ccb1d8dfa5cb7ccd11b324ec1b66ac6d3f4 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:28:53 -0700 Subject: [PATCH 101/223] Restore `dotnet pack` functionality (#118) ## Description of Changes Single-line change so that `dotnet pack` stops complaining that nothing was generated. Per @RReverser this brings this package more in line with our other C# packages. ## API Nah nothing breaking. ## Requires SpacetimeDB PRs Nope --------- Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 6600c39ef66..0452f819647 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -5,7 +5,6 @@ 9 disable enable - True SpacetimeDB.ClientSDK SpacetimeDB SDK jdetter From 2efa162ce9183efc767cb9f0799e322e208aeba1 Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Wed, 7 Aug 2024 13:39:13 -0400 Subject: [PATCH 102/223] Update DEVELOP.md to reflect new codegen (#119) Also ran it again, committing a few generation changes too :) --- sdks/csharp/DEVELOP.md | 17 +++------------- .../src/SpacetimeDB/ClientApi/CallReducer.cs | 5 ++--- .../SpacetimeDB/ClientApi/ClientMessage.cs | 1 + .../SpacetimeDB/ClientApi/DatabaseUpdate.cs | 3 ++- .../src/SpacetimeDB/ClientApi/EnergyQuanta.cs | 3 ++- .../SpacetimeDB/ClientApi/IdentityToken.cs | 5 ++--- .../ClientApi/InitialSubscription.cs | 5 ++--- .../src/SpacetimeDB/ClientApi/OneOffQuery.cs | 4 ++-- .../ClientApi/OneOffQueryResponse.cs | 8 +++----- .../src/SpacetimeDB/ClientApi/OneOffTable.cs | 6 +++--- .../SpacetimeDB/ClientApi/ReducerCallInfo.cs | 6 ++---- .../SpacetimeDB/ClientApi/ServerMessage.cs | 1 + .../src/SpacetimeDB/ClientApi/Subscribe.cs | 4 ++-- .../src/SpacetimeDB/ClientApi/TableUpdate.cs | 10 ++++------ .../ClientApi/TransactionUpdate.cs | 7 +------ sdks/csharp/tools/gen-client-api.bat | 20 +++++++++++++++++++ sdks/csharp/tools/gen-client-api.sh | 15 ++++++++++++++ 17 files changed, 67 insertions(+), 53 deletions(-) create mode 100644 sdks/csharp/tools/gen-client-api.bat create mode 100644 sdks/csharp/tools/gen-client-api.sh diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index de08bc707b4..4f24f4d60cd 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -1,17 +1,6 @@ # Notes for maintainers -## `ClientApi.cs` +## `SpacetimeDB.ClientApi` -The file `ClientApi.cs` is generated by [ProtoBuf](https://protobuf.dev/) -from [the SpacetimeDB client-api-messages proto definition](https://github.com/clockworklabs/SpacetimeDB/blob/master/crates/client-api-messages/protobuf/client_api.proto). -This is not automated. -Whenever the `client_api.proto` changes, you'll have to manually re-run `protoc` to re-generate the definitions. - -```sh -cd ~/clockworklabs/SpacetimeDB/crates/client-api-messages/protobuf -protoc --csharp_out=/absolute/path/to/spacetimedb-csharp-sdk/src \ - ./client_api.proto -``` - -Note that `protoc` cannot understand paths that start with `~`; -you must write the absolute path starting from `/`. +To regenerate this namespace, run the `tools/gen-client-api.sh` or the +`tools/gen-client-api.bat` script. diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs index 0d065d40658..d3f56f381ca 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs @@ -12,17 +12,16 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class CallReducer { [DataMember(Name = "reducer")] public string Reducer = ""; - [DataMember(Name = "args")] public SpacetimeDB.ClientApi.EncodedValue Args = null!; - [DataMember(Name = "request_id")] public uint RequestId; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs index 4badf680709..9cb1c4c7374 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs @@ -5,6 +5,7 @@ #nullable enable using System; +using SpacetimeDB; namespace SpacetimeDB.ClientApi { diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs index 0cf2567e4d9..245117ad702 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs @@ -12,11 +12,12 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class DatabaseUpdate { [DataMember(Name = "tables")] public System.Collections.Generic.List Tables = new(); + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs index 7cd07b36fbe..ba142cb3385 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs @@ -12,11 +12,12 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class EnergyQuanta { [DataMember(Name = "quanta")] public U128 Quanta; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs index b1bbd183e20..344cbbba87e 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs @@ -12,17 +12,16 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class IdentityToken { [DataMember(Name = "identity")] public SpacetimeDB.Identity Identity = new(); - [DataMember(Name = "token")] public string Token = ""; - [DataMember(Name = "address")] public SpacetimeDB.Address Address = new(); + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs index ed704238c7f..06ae7ba854e 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs @@ -12,17 +12,16 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class InitialSubscription { [DataMember(Name = "database_update")] public SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate = new(); - [DataMember(Name = "request_id")] public uint RequestId; - [DataMember(Name = "total_host_execution_duration_micros")] public ulong TotalHostExecutionDurationMicros; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs index c4625fe5450..c103c829f52 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class OneOffQuery { [DataMember(Name = "message_id")] public byte[] MessageId = Array.Empty(); - [DataMember(Name = "query_string")] public string QueryString = ""; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs index 4e98289fca6..35c1d0eb907 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs @@ -12,20 +12,18 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class OneOffQueryResponse { [DataMember(Name = "message_id")] public byte[] MessageId = Array.Empty(); - [DataMember(Name = "error")] public string? Error; - [DataMember(Name = "tables")] - public List Tables = new(); - + public System.Collections.Generic.List Tables = new(); [DataMember(Name = "total_host_execution_duration_micros")] public ulong TotalHostExecutionDurationMicros; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs index 84fa81bf6d2..12f7e0f9d2b 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class OneOffTable { [DataMember(Name = "table_name")] public string TableName = ""; - [DataMember(Name = "rows")] - public List Rows = new(); + public System.Collections.Generic.List Rows = new(); + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs index 86a67416429..44bc88654c5 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs @@ -12,20 +12,18 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class ReducerCallInfo { [DataMember(Name = "reducer_name")] public string ReducerName = ""; - [DataMember(Name = "reducer_id")] public uint ReducerId; - [DataMember(Name = "args")] public SpacetimeDB.ClientApi.EncodedValue Args = null!; - [DataMember(Name = "request_id")] public uint RequestId; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs index 7f4bf714e9a..46b5be3adb7 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs @@ -5,6 +5,7 @@ #nullable enable using System; +using SpacetimeDB; namespace SpacetimeDB.ClientApi { diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs index e844a34799c..d5eaba815a2 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class Subscribe { [DataMember(Name = "query_strings")] public System.Collections.Generic.List QueryStrings = new(); - [DataMember(Name = "request_id")] public uint RequestId; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs index 63400ee6a5d..b9b47ea5d91 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs @@ -12,20 +12,18 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class TableUpdate { [DataMember(Name = "table_id")] public uint TableId; - [DataMember(Name = "table_name")] public string TableName = ""; - [DataMember(Name = "deletes")] - public List Deletes = new(); - + public System.Collections.Generic.List Deletes = new(); [DataMember(Name = "inserts")] - public List Inserts = new(); + public System.Collections.Generic.List Inserts = new(); + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs index 5861e9eef30..fb71dd9e318 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs @@ -18,23 +18,18 @@ public partial class TransactionUpdate { [DataMember(Name = "status")] public SpacetimeDB.ClientApi.UpdateStatus Status = null!; - [DataMember(Name = "timestamp")] public SpacetimeDB.ClientApi.Timestamp Timestamp = new(); - [DataMember(Name = "caller_identity")] public SpacetimeDB.Identity CallerIdentity = new(); - [DataMember(Name = "caller_address")] public SpacetimeDB.Address CallerAddress = new(); - [DataMember(Name = "reducer_call")] public SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall = new(); - [DataMember(Name = "energy_quanta_used")] public SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed = new(); - [DataMember(Name = "host_execution_duration_micros")] public ulong HostExecutionDurationMicros; + } } diff --git a/sdks/csharp/tools/gen-client-api.bat b/sdks/csharp/tools/gen-client-api.bat new file mode 100644 index 00000000000..9eb66c49cdc --- /dev/null +++ b/sdks/csharp/tools/gen-client-api.bat @@ -0,0 +1,20 @@ +@echo off +setlocal + +if "%CL_HOME%"=="" ( + echo "Variable CL_HOME not set" + exit /b 1 +) + +cd %CL_HOME%\SpacetimeDB\crates\client-api-messages +cargo run --example get_ws_schema > %CL_HOME%/schema.json + +cd %CL_HOME%\SpacetimeDB\crates\cli +cargo run -- generate -l csharp -n SpacetimeDB.ClientApi ^ + --json-module %CL_HOME%\schema.json ^ + -o %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi + +cd %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi +del /q _Globals + +del %CL_HOME%\schema.json diff --git a/sdks/csharp/tools/gen-client-api.sh b/sdks/csharp/tools/gen-client-api.sh new file mode 100644 index 00000000000..91fbe3dab83 --- /dev/null +++ b/sdks/csharp/tools/gen-client-api.sh @@ -0,0 +1,15 @@ +#!/bin/sh -eu +: $CL_HOME + +cd $CL_HOME/SpacetimeDB/crates/client-api-messages +cargo run --example get_ws_schema > $CL_HOME/schema.json + +cd $CL_HOME/SpacetimeDB/crates/cli +cargo run -- generate -l csharp -n SpacetimeDB.ClientApi \ + --json-module $CL_HOME/schema.json \ + -o $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi + +cd $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi +rm -rf _Globals + +rm -f $CL_HOME/schema.json From 996633bebc5dbafcfe7fc1fcb2bd37a8dc514f6f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 13 Aug 2024 22:02:39 +0200 Subject: [PATCH 103/223] Nix `Primitives.cs` - types now defined in main repo (#120) ## Description of Changes These types have been moved to the main repo, where they are used by bindings-csharp as well. ## Requires SpacetimeDB PRs - https://github.com/clockworklabs/SpacetimeDB/pull/1477 --------- Co-authored-by: Ingvar Stepanyan Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 +- sdks/csharp/src/Primitives.cs | 83 ------------------------ sdks/csharp/tests/SnapshotTests.cs | 16 ++--- 3 files changed, 6 insertions(+), 97 deletions(-) delete mode 100644 sdks/csharp/src/Primitives.cs diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 0452f819647..2b8c7a2d57e 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,13 +16,13 @@ logo.png README.md https://github.com/clockworklabs/spacetimedb-csharp-sdk - 0.11.0 + 0.12.0 $(AssemblyVersion) $(DefaultItemExcludes);examples/**;tests/** - + diff --git a/sdks/csharp/src/Primitives.cs b/sdks/csharp/src/Primitives.cs deleted file mode 100644 index 93ba5e982ae..00000000000 --- a/sdks/csharp/src/Primitives.cs +++ /dev/null @@ -1,83 +0,0 @@ -using SpacetimeDB.BSATN; - -using System; -using System.IO; - -namespace SpacetimeDB -{ - - public struct I128 : IEquatable - { - public long hi; - public ulong lo; - - public I128(long hi, ulong lo) - { - this.hi = hi; - this.lo = lo; - } - - public readonly bool Equals(I128 x) => hi == x.hi && lo == x.lo; - - public override readonly bool Equals(object? o) => o is I128 x && Equals(x); - - public static bool operator ==(I128 a, I128 b) => a.Equals(b); - public static bool operator !=(I128 a, I128 b) => !a.Equals(b); - - public override readonly int GetHashCode() => hi.GetHashCode() ^ lo.GetHashCode(); - - public override readonly string ToString() => $"I128({hi},{lo})"; - - public readonly struct BSATN : IReadWrite - { - public I128 Read(BinaryReader reader) => new(reader.ReadInt64(), reader.ReadUInt64()); - - public void Write(BinaryWriter writer, I128 value) - { - writer.Write(value.hi); - writer.Write(value.lo); - } - - public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.I128(new Unit()); - } - } - - public struct U128 : IEquatable - { - public ulong hi; - public ulong lo; - - public U128(ulong hi, ulong lo) - { - this.lo = lo; - this.hi = hi; - } - - public readonly bool Equals(U128 x) => hi == x.hi && lo == x.lo; - - public override readonly bool Equals(object? o) => o is U128 x && Equals(x); - - public static bool operator ==(U128 a, U128 b) => a.Equals(b); - public static bool operator !=(U128 a, U128 b) => !a.Equals(b); - - public override readonly int GetHashCode() => hi.GetHashCode() ^ lo.GetHashCode(); - - public override readonly string ToString() => $"U128({hi},{lo})"; - - public readonly struct BSATN : IReadWrite - { - public U128 Read(BinaryReader reader) => new(reader.ReadUInt64(), reader.ReadUInt64()); - - public void Write(BinaryWriter writer, U128 value) - { - writer.Write(value.hi); - writer.Write(value.lo); - } - - public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.U128(new Unit()); - } - } - -} diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests/SnapshotTests.cs index 8f722b3cfe0..af4364c1d1d 100644 --- a/sdks/csharp/tests/SnapshotTests.cs +++ b/sdks/csharp/tests/SnapshotTests.cs @@ -43,23 +43,15 @@ class EnergyQuantaConverter : WriteOnlyJsonConverter { public override void Write(VerifyJsonWriter writer, EnergyQuanta value) { - Assert.Equal(0uL, value.Quanta.hi); - writer.WriteValue(value.Quanta.lo); + writer.WriteRawValueIfNoStrict(value.Quanta.ToString()); } } - class EncodedValueConverter : WriteOnlyJsonConverter + class EncodedValueConverter : WriteOnlyJsonConverter { - public override void Write(VerifyJsonWriter writer, EncodedValue value) + public override void Write(VerifyJsonWriter writer, EncodedValue.Binary value) { - if (value is EncodedValue.Binary(var bytes)) - { - writer.WriteValue(bytes); - } - else - { - throw new InvalidOperationException(); - } + writer.WriteValue(value.Binary_); } } From cb59ebac9954632f6b870018c839ebf9b34c05a0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 28 Aug 2024 19:13:33 +0100 Subject: [PATCH 104/223] Merge Unity SDK into C# SDK (#117) ## Description of Changes This creates a frankenstein monster of a repo that is compatible with both .NET / MSBuild as well as can be consumed as a Unity package. - `.meta` files, Unity manifests and Unity README were copied over from the Unity repo. - `examples` and `tests` folders were renamed to `examples~` and `tests~` correspondingly, as the `~` suffix is the only way to get entire folders ignored by Unity. - MSBuild was configured to change `bin` and `obj` to `bin~` and `obj~` for the same reasons. This doesn't matter for the Git repo, but helpful for local development where you don't want Unity to try and load local DLL artifacts. - NuGet was configured to restore Unity-compatible NuGet DLLs (and delete others) in a local folder and committed to the repo - so, from now on, we can easily update them by modifying `.csproj` and via standard `dotnet restore` / `dotnet build`. After this change, this repo should be compatible with both .NET CLI (e.g. `dotnet test`) as well as consumable from Unity, but due to amount of metadata changes, it needs further testing before we merge repos properly. Fixes #114. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --------- Co-authored-by: Zeke Foppa --- sdks/csharp/.gitignore | 192 ++++++------------ sdks/csharp/DEVELOP.md.meta | 7 + sdks/csharp/Directory.Build.props | 6 + sdks/csharp/Directory.Build.props.meta | 7 + sdks/csharp/LICENSE.txt.meta | 7 + sdks/csharp/README.dotnet.md | 133 ++++++++++++ sdks/csharp/README.dotnet.md.meta | 7 + sdks/csharp/README.md | 54 ++--- sdks/csharp/README.md.meta | 7 + sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 +- sdks/csharp/SpacetimeDB.ClientSDK.csproj.meta | 7 + sdks/csharp/SpacetimeDB.ClientSDK.sln | 4 +- sdks/csharp/SpacetimeDB.ClientSDK.sln.meta | 7 + .../after.SpacetimeDB.ClientSDK.sln.targets | 11 + ...ter.SpacetimeDB.ClientSDK.sln.targets.meta | 7 + .../quickstart/client/Program.cs | 0 .../quickstart/client/client.csproj | 32 +-- .../client/module_bindings/Message.cs | 0 .../module_bindings/SendMessageReducer.cs | 0 .../client/module_bindings/SetNameReducer.cs | 0 .../quickstart/client/module_bindings/User.cs | 0 .../_Globals/SpacetimeDBClient.cs | 0 .../_Globals/UnityNetworkManager.cs | 0 .../quickstart/server/.cargo/config.toml | 0 .../quickstart/server/.gitignore | 0 .../quickstart/server/Cargo.lock | 0 .../quickstart/server/Cargo.toml | 0 .../quickstart/server/src/lib.rs | 0 sdks/csharp/logo.png.meta | 114 +++++++++++ sdks/csharp/package.json | 17 ++ sdks/csharp/package.json.meta | 7 + sdks/csharp/packages.meta | 8 + sdks/csharp/packages/.gitignore | 8 + .../packages/spacetimedb.bsatn.runtime.meta | 8 + .../spacetimedb.bsatn.runtime/0.11.0.meta | 8 + .../0.11.0/analyzers.meta | 8 + .../0.11.0/analyzers/dotnet.meta | 8 + .../0.11.0/analyzers/dotnet/cs.meta | 8 + .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 0 -> 47616 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 71 +++++++ .../spacetimedb.bsatn.runtime/0.11.0/lib.meta | 8 + .../0.11.0/lib/netstandard2.1.meta | 8 + .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 52736 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 33 +++ sdks/csharp/src.meta | 8 + sdks/csharp/src/AuthToken.cs.meta | 11 + sdks/csharp/src/BSATNHelpers.cs.meta | 11 + sdks/csharp/src/ClientCache.cs.meta | 11 + sdks/csharp/src/ConsoleLogger.cs.meta | 11 + sdks/csharp/src/IDatabaseTable.cs.meta | 11 + sdks/csharp/src/ISpacetimeDBLogger.cs.meta | 11 + sdks/csharp/src/Primitives.cs.meta | 11 + sdks/csharp/src/SpacetimeDB.meta | 8 + sdks/csharp/src/SpacetimeDB/ClientApi.meta | 8 + .../SpacetimeDB/ClientApi/CallReducer.cs.meta | 11 + .../ClientApi/ClientMessage.cs.meta | 11 + .../ClientApi/DatabaseUpdate.cs.meta | 11 + .../ClientApi/EncodedValue.cs.meta | 11 + .../ClientApi/EnergyQuanta.cs.meta | 11 + .../ClientApi/IdentityToken.cs.meta | 11 + .../ClientApi/InitialSubscription.cs.meta | 11 + .../SpacetimeDB/ClientApi/OneOffQuery.cs.meta | 11 + .../ClientApi/OneOffQueryResponse.cs.meta | 11 + .../SpacetimeDB/ClientApi/OneOffTable.cs.meta | 11 + .../ClientApi/ReducerCallInfo.cs.meta | 11 + .../ClientApi/ServerMessage.cs.meta | 11 + .../SpacetimeDB/ClientApi/Subscribe.cs.meta | 11 + .../SpacetimeDB/ClientApi/TableUpdate.cs.meta | 11 + .../SpacetimeDB/ClientApi/Timestamp.cs.meta | 11 + .../ClientApi/TransactionUpdate.cs.meta | 11 + .../ClientApi/UpdateStatus.cs.meta | 11 + sdks/csharp/src/SpacetimeDBClient.cs.meta | 11 + sdks/csharp/src/Stats.cs.meta | 11 + sdks/csharp/src/Stubs.cs.meta | 11 + sdks/csharp/src/UnityDebugLogger.cs.meta | 11 + sdks/csharp/src/Utils.cs.meta | 11 + sdks/csharp/src/WebSocket.cs.meta | 11 + .../com.clockworklabs.spacetimedbsdk.asmdef | 3 + ...m.clockworklabs.spacetimedbsdk.asmdef.meta | 7 + sdks/csharp/src/csc.rsp | 1 + sdks/csharp/src/csc.rsp.meta | 7 + ...otTests.VerifyAllTablesParsed.verified.txt | 0 .../csharp/{tests => tests~}/SnapshotTests.cs | 0 sdks/csharp/{tests => tests~}/VerifyInit.cs | 0 sdks/csharp/{tests => tests~}/tests.csproj | 2 +- 85 files changed, 1009 insertions(+), 171 deletions(-) create mode 100644 sdks/csharp/DEVELOP.md.meta create mode 100644 sdks/csharp/Directory.Build.props create mode 100644 sdks/csharp/Directory.Build.props.meta create mode 100644 sdks/csharp/LICENSE.txt.meta create mode 100644 sdks/csharp/README.dotnet.md create mode 100644 sdks/csharp/README.dotnet.md.meta create mode 100644 sdks/csharp/README.md.meta create mode 100644 sdks/csharp/SpacetimeDB.ClientSDK.csproj.meta create mode 100644 sdks/csharp/SpacetimeDB.ClientSDK.sln.meta create mode 100644 sdks/csharp/after.SpacetimeDB.ClientSDK.sln.targets create mode 100644 sdks/csharp/after.SpacetimeDB.ClientSDK.sln.targets.meta rename sdks/csharp/{examples => examples~}/quickstart/client/Program.cs (100%) rename sdks/csharp/{examples => examples~}/quickstart/client/client.csproj (95%) rename sdks/csharp/{examples => examples~}/quickstart/client/module_bindings/Message.cs (100%) rename sdks/csharp/{examples => examples~}/quickstart/client/module_bindings/SendMessageReducer.cs (100%) rename sdks/csharp/{examples => examples~}/quickstart/client/module_bindings/SetNameReducer.cs (100%) rename sdks/csharp/{examples => examples~}/quickstart/client/module_bindings/User.cs (100%) rename sdks/csharp/{examples => examples~}/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs (100%) rename sdks/csharp/{examples => examples~}/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs (100%) rename sdks/csharp/{examples => examples~}/quickstart/server/.cargo/config.toml (100%) rename sdks/csharp/{examples => examples~}/quickstart/server/.gitignore (100%) rename sdks/csharp/{examples => examples~}/quickstart/server/Cargo.lock (100%) rename sdks/csharp/{examples => examples~}/quickstart/server/Cargo.toml (100%) rename sdks/csharp/{examples => examples~}/quickstart/server/src/lib.rs (100%) create mode 100644 sdks/csharp/logo.png.meta create mode 100644 sdks/csharp/package.json create mode 100644 sdks/csharp/package.json.meta create mode 100644 sdks/csharp/packages.meta create mode 100644 sdks/csharp/packages/.gitignore create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime.meta create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0.meta create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers.meta create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet.meta create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs.meta create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib.meta create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1.meta create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta create mode 100644 sdks/csharp/src.meta create mode 100644 sdks/csharp/src/AuthToken.cs.meta create mode 100644 sdks/csharp/src/BSATNHelpers.cs.meta create mode 100644 sdks/csharp/src/ClientCache.cs.meta create mode 100644 sdks/csharp/src/ConsoleLogger.cs.meta create mode 100644 sdks/csharp/src/IDatabaseTable.cs.meta create mode 100644 sdks/csharp/src/ISpacetimeDBLogger.cs.meta create mode 100644 sdks/csharp/src/Primitives.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDBClient.cs.meta create mode 100644 sdks/csharp/src/Stats.cs.meta create mode 100644 sdks/csharp/src/Stubs.cs.meta create mode 100644 sdks/csharp/src/UnityDebugLogger.cs.meta create mode 100644 sdks/csharp/src/Utils.cs.meta create mode 100644 sdks/csharp/src/WebSocket.cs.meta create mode 100644 sdks/csharp/src/com.clockworklabs.spacetimedbsdk.asmdef create mode 100644 sdks/csharp/src/com.clockworklabs.spacetimedbsdk.asmdef.meta create mode 100644 sdks/csharp/src/csc.rsp create mode 100644 sdks/csharp/src/csc.rsp.meta rename sdks/csharp/{tests => tests~}/SnapshotTests.VerifyAllTablesParsed.verified.txt (100%) rename sdks/csharp/{tests => tests~}/SnapshotTests.cs (100%) rename sdks/csharp/{tests => tests~}/VerifyInit.cs (100%) rename sdks/csharp/{tests => tests~}/tests.csproj (91%) diff --git a/sdks/csharp/.gitignore b/sdks/csharp/.gitignore index 5a51aeffefd..825b31b18e0 100644 --- a/sdks/csharp/.gitignore +++ b/sdks/csharp/.gitignore @@ -1,137 +1,77 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files +# This .gitignore file should be placed at the root of your Unity project directory +# +# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore +# +/[Ll]ibrary/ +/[Tt]emp/ +/[Oo]bj/ +/[Bb]uild/ +/[Bb]uilds/ +/[Ll]ogs/ +/[Uu]ser[Ss]ettings/ + +# MemoryCaptures can get excessive in size. +# They also could contain extremely sensitive data +/[Mm]emoryCaptures/ + +# Recordings can get excessive in size +/[Rr]ecordings/ + +# Uncomment this line if you wish to ignore the asset store tools plugin +# /[Aa]ssets/AssetStoreTools* + +# Autogenerated Jetbrains Rider plugin +/[Aa]ssets/Plugins/Editor/JetBrains* + +# Visual Studio cache directory +.vs/ + +# Gradle cache directory +.gradle/ + +# Autogenerated VS/MD/Consulo solution and project files +ExportedObj/ +.consulo/ +*.unityproj *.suo -*.user -*.sln.docstates - -# Build results - -[Dd]ebug/ -[Rr]elease/ -x64/ -[Bb]in/ -[Oo]bj/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh *.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds +*.user +*.userprefs *.pidb -*.log -*.svclog -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml -*.azurePubxml - -# NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line -packages/ -## TODO: If the tool you use requires repositories.config, also uncomment the next line -!packages/repositories.config - -# Windows Azure Build Output -csx/ -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -![Ss]tyle[Cc]op.targets -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -.vs - -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm +*.booproj +*.svd +*.pdb +*.mdb +*.opendb +*.VC.db -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf +# Unity3D generated meta files +*.pidb.meta +*.pdb.meta +*.mdb.meta -# ========================= -# Windows detritus -# ========================= +# Unity3D generated file on crash reports +sysinfo.txt -# Windows image file caches -Thumbs.db -ehthumbs.db +# Builds +*.apk +*.aab +*.unitypackage +*.app -# Folder config file -Desktop.ini +# Crashlytics generated file +crashlytics-build.properties -# Recycle Bin used on file shares -$RECYCLE.BIN/ +# Packed Addressables +/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* -# Mac desktop service store files -.DS_Store +# Temporary auto-generated Android Assets +/[Aa]ssets/[Ss]treamingAssets/aa.meta +/[Aa]ssets/[Ss]treamingAssets/aa/* -_NCrunch* +bin~ +obj~ -# JetBrains Ignore -.idea/ +# This is used for local paths to SpacetimeDB packages. +/nuget.config +/nuget.config.meta diff --git a/sdks/csharp/DEVELOP.md.meta b/sdks/csharp/DEVELOP.md.meta new file mode 100644 index 00000000000..eeac4b35ea6 --- /dev/null +++ b/sdks/csharp/DEVELOP.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a3279c10dee07d74daa647909f7882bf +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/Directory.Build.props b/sdks/csharp/Directory.Build.props new file mode 100644 index 00000000000..2bf91e9708f --- /dev/null +++ b/sdks/csharp/Directory.Build.props @@ -0,0 +1,6 @@ + + + bin~ + obj~ + + diff --git a/sdks/csharp/Directory.Build.props.meta b/sdks/csharp/Directory.Build.props.meta new file mode 100644 index 00000000000..c7afb4971f3 --- /dev/null +++ b/sdks/csharp/Directory.Build.props.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e8c57a282e7de1f4788630d42ea90a3d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/LICENSE.txt.meta b/sdks/csharp/LICENSE.txt.meta new file mode 100644 index 00000000000..cc52583fa8c --- /dev/null +++ b/sdks/csharp/LICENSE.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a9576a820941d4473b81734019e6bae4 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/README.dotnet.md b/sdks/csharp/README.dotnet.md new file mode 100644 index 00000000000..82c2fc47aad --- /dev/null +++ b/sdks/csharp/README.dotnet.md @@ -0,0 +1,133 @@ +# SpacetimeDB SDK for C# + +## Overview + +This repository contains the [C#](https://learn.microsoft.com/en-us/dotnet/csharp/) SDK for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. + +## Documentation + +The C# SDK has a [Quick Start](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-quickstart-guide) guide and a [Reference](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-reference). + +## Installation + +The SDK is available as a [NuGet Package](https://www.nuget.org/packages/SpacetimeDB.ClientSDK). To install it, follow these steps: + +1. Open the NuGet package manager in Visual Studio. +2. Search for `SpacetimeDB.ClientSDK`. +3. Click the install button. + +Alternatively, it can be installed on the command line using the `dotnet` command: + +```bash +dotnet add package SpacetimeDB.ClientSDK +``` + +## Usage + +### Access the SpacetimeDB Client + +The SpacetimeDB client is created automatically as a singleton and accessible via the `SpacetimeDBClient.instance` property. + +### Connecting to SpacetimeDB + +To connect to SpacetimeDB, you need to call the `Connect` method on the `SpacetimeDBClient` class. The `Connect` method takes the following parameters: + +- `token`: The authentication token to use to connect to SpacetimeDB. This token is generated by the backend code and is used to authenticate the client. +- `hostName`: The hostname of the SpacetimeDB server. This is the same hostname that you use to connect to the SpacetimeDB web interface. +- `moduleAddress`: The address of the module to connect to. This is the same address that you use to connect to the SpacetimeDB web interface. +- `sslEnabled`: Whether to use SSL to connect to SpacetimeDB. This is the same value that you use to connect to the SpacetimeDB web interface. + +Example: + +```csharp +using SpacetimeDB; + +SpacetimeDBClient.instance.Connect(TOKEN, HOST, DBNAME, SSL_ENABLED); +``` + +### AuthToken optional helper class + +The `AuthToken` class is a helper class that can be used to store the local client's authentication token locally to your user's home directory. + +```csharp +using SpacetimeDB; + +AuthToken.Init(".spacetime_csharp_quickstart"); + +SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME, SSL_ENABLED); + +void OnIdentityReceived(string authToken, Identity identity) +{ + local_identity = identity; + AuthToken.SaveToken(authToken); +} +SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; +``` + +### Subscribing to tables + +To subscribe to a table, you need to call the `Subscribe` method on the `SpacetimeDBClient` class. The `Subscribe` method takes a list of queries as a parameter. The queries are the same queries that you use to subscribe to tables in the SpacetimeDB web interface. + +### Listening to events + +To listen to events, you need to register callbacks on the `SpacetimeDBClient` class. The following callbacks are available: + +- `onConnect`: Called when the client connects to SpacetimeDB. +- `onConnectError`: Called when the client fails to connect to SpacetimeDB. +- `onDisconnect`: Called when the client disconnects from SpacetimeDB. +- `onIdentityReceived`: Called when the client receives its identity from SpacetimeDB. +- `onSubscriptionApplied`: Called when the client receives the initial data from SpacetimeDB after subscribing to tables. + +You can register for row update events on a table. To do this, you need to register callbacks on the table class. The following callbacks are available: + +- `OnInsert`: Called when a row is inserted into the table. +- `OnUpdate`: Called when a row is updated in the table. +- `OnBeforeDelete`: Called before a row is deleted from the table. +- `OnDelete`: Called when a row is deleted from the table. + +Example: + +```csharp +using SpacetimeDB.Types; + +PlayerComponent.OnInsert += PlayerComponent_OnInsert; +PlayerComponent.OnUpdate += PlayerComponent_OnUpdate; +PlayerComponent.OnDelete += PlayerComponent_OnDelete; +PlayerComponent.OnBeforeDelete += PlayerComponent_OnBeforeDelete; +``` + +You can register for reducer call updates as well. + +- `OnREDUCEREvent`: Called when a reducer call is received from SpacetimeDB. (If a) you are subscribed to the table that the reducer modifies or b) You called the reducer and it failed) + +Example: + +```csharp +using SpacetimeDB.Types; + +Reducer.OnMovePlayerEvent += Reducer_OnMovePlayerEvent; +``` + +### Accessing the client cache + +The client cache is a local cache of the data that the client has received from SpacetimeDB. The client cache is automatically updated when the client receives updates from SpacetimeDB. + +When you run the CLI generate command, SpacetimeDB will automatically generate a class for each table in your database. These classes are generated in the `SpacetimeDB.Types` namespace. Each class contains a set of static methods that allow you to query the client cache. The following methods are available: + +- `int Count()`: Returns the number of rows in the table. +- `IEnumerable Iter()`: Returns an iterator over the table. +- `IEnumerable FilterByCOLUMN(ColumnValue)`: Filters the table by the specified column value. +- `TableRow? FindByCOLUMN(ColumnValue)`: Finds a single item by the specifed column value. +- `IEnumerable Query(Func)`: Filters the table with the specified predicate. + +### Calling Reducers + +To call a reducer, you need to call the autogenerated method on the `Reducer` class. The autogenerated method takes the reducer arguments as parameters. The reducer arguments are the same arguments that are expected in your server module. + +Example: + +```csharp +using SpacetimeDB.Types; + +Reducer.MovePlayer(new StdbVector2(0.0f, 0.0f), new StdbVector2(1.0f, 1.0f)); +``` diff --git a/sdks/csharp/README.dotnet.md.meta b/sdks/csharp/README.dotnet.md.meta new file mode 100644 index 00000000000..b6ec098589d --- /dev/null +++ b/sdks/csharp/README.dotnet.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 729cacf01d1965648a5acf0dfa38b2a9 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 82c2fc47aad..189d6612894 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -1,32 +1,35 @@ -# SpacetimeDB SDK for C# +# SpacetimeDB SDK for Unity Engine ## Overview -This repository contains the [C#](https://learn.microsoft.com/en-us/dotnet/csharp/) SDK for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. +This repository contains the [Unity](https://unity.com/) SDK for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. ## Documentation -The C# SDK has a [Quick Start](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-quickstart-guide) guide and a [Reference](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-reference). +The Unity SDK uses the same code as the C# SDK. You can find the documentation for the C# SDK in the [C# SDK Reference](README.dotnet.md). + +There is also a comprehensive Unity tutorial/demo available: + +- [Unity Tutorial](https://spacetimedb.com/docs/unity/part-1) Doc +- [Unity Demo](https://github.com/clockworklabs/SpacetimeDBUnityTutorial) Repo ## Installation -The SDK is available as a [NuGet Package](https://www.nuget.org/packages/SpacetimeDB.ClientSDK). To install it, follow these steps: +### Unity Demo -1. Open the NuGet package manager in Visual Studio. -2. Search for `SpacetimeDB.ClientSDK`. -3. Click the install button. +Download the [.unitypackage release](https://github.com/clockworklabs/SpacetimeDBUnityTutorial/releases) of our [Unity Part 1 tutorial](https://spacetimedb.com/docs/unity/part-1) demo that includes this SDK as a package manfiest requirement. -Alternatively, it can be installed on the command line using the `dotnet` command: +### Standalone -```bash -dotnet add package SpacetimeDB.ClientSDK -``` +1. Open the package manager window in Unity. +2. Click the "(+)" button in the top-left corner and select "Add package from git URL". +3. Paste the following URL: `https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk.git` ## Usage -### Access the SpacetimeDB Client +### UnityNetworkManager -The SpacetimeDB client is created automatically as a singleton and accessible via the `SpacetimeDBClient.instance` property. +The Unity SDK for SpacetimeDB requires that there is a `UnityNetworkManager` component attached to a GameObject in the scene. The `UnityNetworkManager` component is responsible for connecting to SpacetimeDB and managing the connection. The `UnityNetworkManager` component is a singleton and there can only be one instance of it in the scene. ### Connecting to SpacetimeDB @@ -37,7 +40,7 @@ To connect to SpacetimeDB, you need to call the `Connect` method on the `Spaceti - `moduleAddress`: The address of the module to connect to. This is the same address that you use to connect to the SpacetimeDB web interface. - `sslEnabled`: Whether to use SSL to connect to SpacetimeDB. This is the same value that you use to connect to the SpacetimeDB web interface. -Example: +Example: ```csharp using SpacetimeDB; @@ -45,23 +48,22 @@ using SpacetimeDB; SpacetimeDBClient.instance.Connect(TOKEN, HOST, DBNAME, SSL_ENABLED); ``` -### AuthToken optional helper class +### AuthToken -The `AuthToken` class is a helper class that can be used to store the local client's authentication token locally to your user's home directory. +The `AuthToken` class is an optional helper class that can be used to store the local client's authentication token locally in the Unity PlayerPrefs. + +Example: ```csharp using SpacetimeDB; -AuthToken.Init(".spacetime_csharp_quickstart"); - -SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME, SSL_ENABLED); - -void OnIdentityReceived(string authToken, Identity identity) -{ +// called when we receive the client identity from SpacetimeDB +SpacetimeDBClient.instance.onIdentityReceived += (token, identity, address) => { + AuthToken.SaveToken(token); local_identity = identity; - AuthToken.SaveToken(authToken); -} -SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; +}; + +SpacetimeDBClient.instance.Connect(AuthToken.Token, hostName, moduleAddress, sslEnabled); ``` ### Subscribing to tables @@ -84,6 +86,7 @@ You can register for row update events on a table. To do this, you need to regis - `OnUpdate`: Called when a row is updated in the table. - `OnBeforeDelete`: Called before a row is deleted from the table. - `OnDelete`: Called when a row is deleted from the table. +- `OnRowUpdate`: Called when a row is inserted, updated, or deleted from the table. Example: @@ -94,6 +97,7 @@ PlayerComponent.OnInsert += PlayerComponent_OnInsert; PlayerComponent.OnUpdate += PlayerComponent_OnUpdate; PlayerComponent.OnDelete += PlayerComponent_OnDelete; PlayerComponent.OnBeforeDelete += PlayerComponent_OnBeforeDelete; +PlayerComponent.OnRowUpdate += PlayerComponent_OnRowUpdate; ``` You can register for reducer call updates as well. diff --git a/sdks/csharp/README.md.meta b/sdks/csharp/README.md.meta new file mode 100644 index 00000000000..b69b66ca5a9 --- /dev/null +++ b/sdks/csharp/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dfa7ed0c3892b254eaa47dd935085847 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 2b8c7a2d57e..1c2158b20f7 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -18,7 +18,9 @@ https://github.com/clockworklabs/spacetimedb-csharp-sdk 0.12.0 $(AssemblyVersion) - $(DefaultItemExcludes);examples/**;tests/** + $(DefaultItemExcludes);*~/** + + packages diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj.meta b/sdks/csharp/SpacetimeDB.ClientSDK.csproj.meta new file mode 100644 index 00000000000..31ff15d8f03 --- /dev/null +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5a5d983b907565e4bb3f65ae28133d07 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.sln b/sdks/csharp/SpacetimeDB.ClientSDK.sln index f6836b1ee66..a417d3c74fe 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.sln +++ b/sdks/csharp/SpacetimeDB.ClientSDK.sln @@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.6.33717.318 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples\quickstart\client\client.csproj", "{8F33709C-DEE9-41CC-A477-D6128E3700B1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples~\quickstart\client\client.csproj", "{8F33709C-DEE9-41CC-A477-D6128E3700B1}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpacetimeDB.ClientSDK", "SpacetimeDB.ClientSDK.csproj", "{242A8146-A58D-43E9-A2BD-31FFC6851AA6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests\tests.csproj", "{5CD31104-4719-4CE3-8D39-8BAE0B75C085}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests~\tests.csproj", "{5CD31104-4719-4CE3-8D39-8BAE0B75C085}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.sln.meta b/sdks/csharp/SpacetimeDB.ClientSDK.sln.meta new file mode 100644 index 00000000000..ed9b04626e3 --- /dev/null +++ b/sdks/csharp/SpacetimeDB.ClientSDK.sln.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8dc5bd53630735140b683bfc099bd337 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/after.SpacetimeDB.ClientSDK.sln.targets b/sdks/csharp/after.SpacetimeDB.ClientSDK.sln.targets new file mode 100644 index 00000000000..a9197c5098f --- /dev/null +++ b/sdks/csharp/after.SpacetimeDB.ClientSDK.sln.targets @@ -0,0 +1,11 @@ + + + + + + + <_UnsupportedDLLs Include="packages/**/net8.0/**" /> + + + + diff --git a/sdks/csharp/after.SpacetimeDB.ClientSDK.sln.targets.meta b/sdks/csharp/after.SpacetimeDB.ClientSDK.sln.targets.meta new file mode 100644 index 00000000000..d84b90eb8b5 --- /dev/null +++ b/sdks/csharp/after.SpacetimeDB.ClientSDK.sln.targets.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7081aa46c77e49c4a86d9b626acc712c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/examples/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs similarity index 100% rename from sdks/csharp/examples/quickstart/client/Program.cs rename to sdks/csharp/examples~/quickstart/client/Program.cs diff --git a/sdks/csharp/examples/quickstart/client/client.csproj b/sdks/csharp/examples~/quickstart/client/client.csproj similarity index 95% rename from sdks/csharp/examples/quickstart/client/client.csproj rename to sdks/csharp/examples~/quickstart/client/client.csproj index 45e7e2664e8..93444533e4e 100644 --- a/sdks/csharp/examples/quickstart/client/client.csproj +++ b/sdks/csharp/examples~/quickstart/client/client.csproj @@ -1,16 +1,16 @@ - - - - Exe - net7.0 - disable - enable - - false - - - - - - - + + + + Exe + net7.0 + disable + enable + + false + + + + + + + diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs similarity index 100% rename from sdks/csharp/examples/quickstart/client/module_bindings/Message.cs rename to sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs similarity index 100% rename from sdks/csharp/examples/quickstart/client/module_bindings/SendMessageReducer.cs rename to sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs similarity index 100% rename from sdks/csharp/examples/quickstart/client/module_bindings/SetNameReducer.cs rename to sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs similarity index 100% rename from sdks/csharp/examples/quickstart/client/module_bindings/User.cs rename to sdks/csharp/examples~/quickstart/client/module_bindings/User.cs diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs similarity index 100% rename from sdks/csharp/examples/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs rename to sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs diff --git a/sdks/csharp/examples/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs similarity index 100% rename from sdks/csharp/examples/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs rename to sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs diff --git a/sdks/csharp/examples/quickstart/server/.cargo/config.toml b/sdks/csharp/examples~/quickstart/server/.cargo/config.toml similarity index 100% rename from sdks/csharp/examples/quickstart/server/.cargo/config.toml rename to sdks/csharp/examples~/quickstart/server/.cargo/config.toml diff --git a/sdks/csharp/examples/quickstart/server/.gitignore b/sdks/csharp/examples~/quickstart/server/.gitignore similarity index 100% rename from sdks/csharp/examples/quickstart/server/.gitignore rename to sdks/csharp/examples~/quickstart/server/.gitignore diff --git a/sdks/csharp/examples/quickstart/server/Cargo.lock b/sdks/csharp/examples~/quickstart/server/Cargo.lock similarity index 100% rename from sdks/csharp/examples/quickstart/server/Cargo.lock rename to sdks/csharp/examples~/quickstart/server/Cargo.lock diff --git a/sdks/csharp/examples/quickstart/server/Cargo.toml b/sdks/csharp/examples~/quickstart/server/Cargo.toml similarity index 100% rename from sdks/csharp/examples/quickstart/server/Cargo.toml rename to sdks/csharp/examples~/quickstart/server/Cargo.toml diff --git a/sdks/csharp/examples/quickstart/server/src/lib.rs b/sdks/csharp/examples~/quickstart/server/src/lib.rs similarity index 100% rename from sdks/csharp/examples/quickstart/server/src/lib.rs rename to sdks/csharp/examples~/quickstart/server/src/lib.rs diff --git a/sdks/csharp/logo.png.meta b/sdks/csharp/logo.png.meta new file mode 100644 index 00000000000..5556441e587 --- /dev/null +++ b/sdks/csharp/logo.png.meta @@ -0,0 +1,114 @@ +fileFormatVersion: 2 +guid: c163a0b63c6c06d48a38df66870453e1 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json new file mode 100644 index 00000000000..8f6aa864f7a --- /dev/null +++ b/sdks/csharp/package.json @@ -0,0 +1,17 @@ +{ + "name": "com.clockworklabs.spacetimedbsdk", + "displayName": "SpacetimeDB SDK", + "version": "0.10.0", + "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", + "keywords": [], + "author": { + "name": "Clockwork Labs", + "email": "john@clockworklabs.io", + "url": "https://spacetimedb.com" + }, + "repository": { + "type": "git", + "url": "https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk" + }, + "license": "" +} diff --git a/sdks/csharp/package.json.meta b/sdks/csharp/package.json.meta new file mode 100644 index 00000000000..e630b62c6d8 --- /dev/null +++ b/sdks/csharp/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 22ac4b1e312dc4c438bc4c481f35f1ad +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages.meta b/sdks/csharp/packages.meta new file mode 100644 index 00000000000..6199f35651b --- /dev/null +++ b/sdks/csharp/packages.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2d6701c9b31bc7843b5e8aee47d845c8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/.gitignore b/sdks/csharp/packages/.gitignore new file mode 100644 index 00000000000..5602e9e9759 --- /dev/null +++ b/sdks/csharp/packages/.gitignore @@ -0,0 +1,8 @@ +# Ignore most of NuGet package structure, except DLLs which are required by Unity. +/*/*/* + +!/*/*/analyzers +!/*/*/analyzers.meta + +!/*/*/lib +!/*/*/lib.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime.meta new file mode 100644 index 00000000000..6dc8b62571c --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8865417631feca343997ae22b3320e75 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0.meta new file mode 100644 index 00000000000..db902e53c53 --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c602172ef60d71f41a6a5e85cf41da1a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers.meta new file mode 100644 index 00000000000..aff342ea1f5 --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f112b25d371a72548b6b4959e104c4c3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet.meta new file mode 100644 index 00000000000..f2031f11a56 --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8554a9e409be36a42bdb316f4677fabf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs.meta new file mode 100644 index 00000000000..a387186fa76 --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a24e03405bfe85e4996b2524189ac24a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll new file mode 100644 index 0000000000000000000000000000000000000000..d56f1f0f232ba24dd9c18f50389b15e95ce0f0f6 GIT binary patch literal 47616 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta new file mode 100644 index 00000000000..fcd3478e3fb --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta @@ -0,0 +1,71 @@ +fileFormatVersion: 2 +guid: 31ff25d2b5723480e873b2b8f46bba86 +labels: +- RoslynAnalyzer +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 1 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib.meta new file mode 100644 index 00000000000..3050ce8ab83 --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc6d364d8264f4d43847a2f962630f96 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1.meta new file mode 100644 index 00000000000..56e591b6926 --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b964bd4b6540b3c4e90d73d46afd8fc2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll new file mode 100644 index 0000000000000000000000000000000000000000..0ef9930fd6d81bdeb798f061cb1c6288f05974c8 GIT binary patch literal 52736 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta new file mode 100644 index 00000000000..de2769892f6 --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8ab8f6f35b91340e6b1269b6448e3bf0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src.meta b/sdks/csharp/src.meta new file mode 100644 index 00000000000..6f9561625aa --- /dev/null +++ b/sdks/csharp/src.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e7dd9a5d0c775974facb2bb541db63d6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/AuthToken.cs.meta b/sdks/csharp/src/AuthToken.cs.meta new file mode 100644 index 00000000000..6b2cf78c085 --- /dev/null +++ b/sdks/csharp/src/AuthToken.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44e5948afc80d3a44b2229710cf70531 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/BSATNHelpers.cs.meta b/sdks/csharp/src/BSATNHelpers.cs.meta new file mode 100644 index 00000000000..aa87b84d9a9 --- /dev/null +++ b/sdks/csharp/src/BSATNHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1937244b87cea4904a5c0e9ddfa3d6c4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/ClientCache.cs.meta b/sdks/csharp/src/ClientCache.cs.meta new file mode 100644 index 00000000000..05945aad612 --- /dev/null +++ b/sdks/csharp/src/ClientCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 19daa942f11e07246a9cb65c81ce982a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/ConsoleLogger.cs.meta b/sdks/csharp/src/ConsoleLogger.cs.meta new file mode 100644 index 00000000000..5309056747f --- /dev/null +++ b/sdks/csharp/src/ConsoleLogger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2273bbbdab0d0bf478b6cecee881dcc7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/IDatabaseTable.cs.meta b/sdks/csharp/src/IDatabaseTable.cs.meta new file mode 100644 index 00000000000..a32271541b4 --- /dev/null +++ b/sdks/csharp/src/IDatabaseTable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11f729b0583a241499850598f6d9c870 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/ISpacetimeDBLogger.cs.meta b/sdks/csharp/src/ISpacetimeDBLogger.cs.meta new file mode 100644 index 00000000000..bbf8916172d --- /dev/null +++ b/sdks/csharp/src/ISpacetimeDBLogger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd7303290d31f364da7f532d52cf4914 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/Primitives.cs.meta b/sdks/csharp/src/Primitives.cs.meta new file mode 100644 index 00000000000..3ed18da1cbe --- /dev/null +++ b/sdks/csharp/src/Primitives.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 565602d5968368295b6cf26721a8890a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB.meta b/sdks/csharp/src/SpacetimeDB.meta new file mode 100644 index 00000000000..e4ed673ed6c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 928ddcef9e2fb2d579b8f3558f353913 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi.meta b/sdks/csharp/src/SpacetimeDB/ClientApi.meta new file mode 100644 index 00000000000..5729181e638 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 379cf01a10bd1b3a3999d7a07370ad1a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs.meta new file mode 100644 index 00000000000..26b819171f9 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e26014e7433b503568d0655b46744c4c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs.meta new file mode 100644 index 00000000000..093e2ff4c7e --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4a952c2bbd0c02cc4a8d919c409500f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs.meta new file mode 100644 index 00000000000..d05709fa750 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93a2faf8f0503454bbd2c924554997f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs.meta new file mode 100644 index 00000000000..c89e37b1e22 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 16581799d308744cbba931760b17b64c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs.meta new file mode 100644 index 00000000000..ae82b6330ed --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1deb421d0aa8a992aaf03a2dff20add4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs.meta new file mode 100644 index 00000000000..dd823c173e2 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3afecf9b6bdbec44a9638de844018831 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs.meta new file mode 100644 index 00000000000..3c199551d94 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 164675d4073454c7486c6633c9aff306 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs.meta new file mode 100644 index 00000000000..cf88bb971fa --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69eedb692f165b0c68dc2e5ccb4269a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs.meta new file mode 100644 index 00000000000..fe687a2d46f --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 628b6232147f7f844ad8aab9929e2f07 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs.meta new file mode 100644 index 00000000000..f470acb47d9 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 998830667e639b1999a45be570b59e9b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs.meta new file mode 100644 index 00000000000..4713aefe9f5 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3eb44d3c073528b9b95219f6d4a735c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs.meta new file mode 100644 index 00000000000..f52cc6b3f2f --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 771b9bdf36469247088207291d9a6f59 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs.meta new file mode 100644 index 00000000000..bd51967be17 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11084f5a0b2e1ca908fe4e98cc76c79a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs.meta new file mode 100644 index 00000000000..44d124f89f7 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afe8988a93d28cd3fa95af39bde02f9d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs.meta new file mode 100644 index 00000000000..94af80d6c6e --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 145b8ed3026f531488ee5400d4cb8894 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs.meta new file mode 100644 index 00000000000..37c72e6a18c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 08a42b1306e38dfddbcb0c0fcfc16acf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs.meta new file mode 100644 index 00000000000..ea414a49c01 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2afa3ef5001b6d1439ec004b3956d887 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDBClient.cs.meta b/sdks/csharp/src/SpacetimeDBClient.cs.meta new file mode 100644 index 00000000000..54679b20dc8 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDBClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b2e2257b72c40ac4f94e9fe8a0a1c51c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/Stats.cs.meta b/sdks/csharp/src/Stats.cs.meta new file mode 100644 index 00000000000..aa7e387eca9 --- /dev/null +++ b/sdks/csharp/src/Stats.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 78bde2488f9358148897c778b2ef1e6c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/Stubs.cs.meta b/sdks/csharp/src/Stubs.cs.meta new file mode 100644 index 00000000000..da0198c0c84 --- /dev/null +++ b/sdks/csharp/src/Stubs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0de7dc78e75a21a428bfa6e3dd520ba9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/UnityDebugLogger.cs.meta b/sdks/csharp/src/UnityDebugLogger.cs.meta new file mode 100644 index 00000000000..7a161f3b0e5 --- /dev/null +++ b/sdks/csharp/src/UnityDebugLogger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dca83adbf482a184fae5c66692bfb3f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/Utils.cs.meta b/sdks/csharp/src/Utils.cs.meta new file mode 100644 index 00000000000..750b099f790 --- /dev/null +++ b/sdks/csharp/src/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6bc823297f8396b42b0805bdc1aba85f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/WebSocket.cs.meta b/sdks/csharp/src/WebSocket.cs.meta new file mode 100644 index 00000000000..d99b344827f --- /dev/null +++ b/sdks/csharp/src/WebSocket.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 25629871099f7fb44a41043590bc668f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/com.clockworklabs.spacetimedbsdk.asmdef b/sdks/csharp/src/com.clockworklabs.spacetimedbsdk.asmdef new file mode 100644 index 00000000000..ab9733e7bcb --- /dev/null +++ b/sdks/csharp/src/com.clockworklabs.spacetimedbsdk.asmdef @@ -0,0 +1,3 @@ +{ + "name": "com.clockworklabs.spacetimedbsdk" +} diff --git a/sdks/csharp/src/com.clockworklabs.spacetimedbsdk.asmdef.meta b/sdks/csharp/src/com.clockworklabs.spacetimedbsdk.asmdef.meta new file mode 100644 index 00000000000..83158297096 --- /dev/null +++ b/sdks/csharp/src/com.clockworklabs.spacetimedbsdk.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 51b18aaff8cb8384da535c99b8b52a6b +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/csc.rsp b/sdks/csharp/src/csc.rsp new file mode 100644 index 00000000000..2d66b0292b8 --- /dev/null +++ b/sdks/csharp/src/csc.rsp @@ -0,0 +1 @@ +-nullable:enable diff --git a/sdks/csharp/src/csc.rsp.meta b/sdks/csharp/src/csc.rsp.meta new file mode 100644 index 00000000000..f8faa3aae2d --- /dev/null +++ b/sdks/csharp/src/csc.rsp.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7e009052bf835774fb3593d29e4eb007 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt similarity index 100% rename from sdks/csharp/tests/SnapshotTests.VerifyAllTablesParsed.verified.txt rename to sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt diff --git a/sdks/csharp/tests/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs similarity index 100% rename from sdks/csharp/tests/SnapshotTests.cs rename to sdks/csharp/tests~/SnapshotTests.cs diff --git a/sdks/csharp/tests/VerifyInit.cs b/sdks/csharp/tests~/VerifyInit.cs similarity index 100% rename from sdks/csharp/tests/VerifyInit.cs rename to sdks/csharp/tests~/VerifyInit.cs diff --git a/sdks/csharp/tests/tests.csproj b/sdks/csharp/tests~/tests.csproj similarity index 91% rename from sdks/csharp/tests/tests.csproj rename to sdks/csharp/tests~/tests.csproj index 20dc5b0e6d1..23735fb4623 100644 --- a/sdks/csharp/tests/tests.csproj +++ b/sdks/csharp/tests~/tests.csproj @@ -23,7 +23,7 @@ - + From e28849e22c697a4cd056fd483dcd3a5aa2573565 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 29 Aug 2024 09:21:48 -0700 Subject: [PATCH 105/223] Revert `master` to a stable state (#123) ## Description of Changes Revert `master` to the original state of this PR: https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/53. We should prevent merging into `master` from now on, since the repositories are now merged. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testing I loaded a bitcraft world and ran around. I used the versions listed here: https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk-archive/pull/57 --------- Co-authored-by: Ingvar Stepanyan Co-authored-by: Zeke Foppa --- sdks/csharp/DEVELOP.md | 17 +++- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 5 +- sdks/csharp/src/Primitives.cs | 83 +++++++++++++++++++ .../src/SpacetimeDB/ClientApi/CallReducer.cs | 5 +- .../SpacetimeDB/ClientApi/ClientMessage.cs | 1 - .../SpacetimeDB/ClientApi/DatabaseUpdate.cs | 3 +- .../src/SpacetimeDB/ClientApi/EnergyQuanta.cs | 3 +- .../SpacetimeDB/ClientApi/IdentityToken.cs | 5 +- .../ClientApi/InitialSubscription.cs | 5 +- .../src/SpacetimeDB/ClientApi/OneOffQuery.cs | 4 +- .../ClientApi/OneOffQueryResponse.cs | 8 +- .../src/SpacetimeDB/ClientApi/OneOffTable.cs | 6 +- .../SpacetimeDB/ClientApi/ReducerCallInfo.cs | 6 +- .../SpacetimeDB/ClientApi/ServerMessage.cs | 1 - .../src/SpacetimeDB/ClientApi/Subscribe.cs | 4 +- .../src/SpacetimeDB/ClientApi/TableUpdate.cs | 10 ++- .../ClientApi/TransactionUpdate.cs | 7 +- sdks/csharp/tests~/SnapshotTests.cs | 16 +++- sdks/csharp/tools/gen-client-api.bat | 20 ----- sdks/csharp/tools/gen-client-api.sh | 15 ---- 20 files changed, 151 insertions(+), 73 deletions(-) create mode 100644 sdks/csharp/src/Primitives.cs delete mode 100644 sdks/csharp/tools/gen-client-api.bat delete mode 100644 sdks/csharp/tools/gen-client-api.sh diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index 4f24f4d60cd..de08bc707b4 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -1,6 +1,17 @@ # Notes for maintainers -## `SpacetimeDB.ClientApi` +## `ClientApi.cs` -To regenerate this namespace, run the `tools/gen-client-api.sh` or the -`tools/gen-client-api.bat` script. +The file `ClientApi.cs` is generated by [ProtoBuf](https://protobuf.dev/) +from [the SpacetimeDB client-api-messages proto definition](https://github.com/clockworklabs/SpacetimeDB/blob/master/crates/client-api-messages/protobuf/client_api.proto). +This is not automated. +Whenever the `client_api.proto` changes, you'll have to manually re-run `protoc` to re-generate the definitions. + +```sh +cd ~/clockworklabs/SpacetimeDB/crates/client-api-messages/protobuf +protoc --csharp_out=/absolute/path/to/spacetimedb-csharp-sdk/src \ + ./client_api.proto +``` + +Note that `protoc` cannot understand paths that start with `~`; +you must write the absolute path starting from `/`. diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 1c2158b20f7..72a34580a96 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -5,6 +5,7 @@ 9 disable enable + True SpacetimeDB.ClientSDK SpacetimeDB SDK jdetter @@ -16,7 +17,7 @@ logo.png README.md https://github.com/clockworklabs/spacetimedb-csharp-sdk - 0.12.0 + 0.11.0 $(AssemblyVersion) $(DefaultItemExcludes);*~/** @@ -24,7 +25,7 @@ - + diff --git a/sdks/csharp/src/Primitives.cs b/sdks/csharp/src/Primitives.cs new file mode 100644 index 00000000000..9466cca5711 --- /dev/null +++ b/sdks/csharp/src/Primitives.cs @@ -0,0 +1,83 @@ +using SpacetimeDB.BSATN; + +using System; +using System.IO; + +namespace SpacetimeDB +{ + + public struct I128 : IEquatable + { + public long hi; + public ulong lo; + + public I128(long hi, ulong lo) + { + this.hi = hi; + this.lo = lo; + } + + public readonly bool Equals(I128 x) => hi == x.hi && lo == x.lo; + + public override readonly bool Equals(object? o) => o is I128 x && Equals(x); + + public static bool operator ==(I128 a, I128 b) => a.Equals(b); + public static bool operator !=(I128 a, I128 b) => !a.Equals(b); + + public override readonly int GetHashCode() => hi.GetHashCode() ^ lo.GetHashCode(); + + public override readonly string ToString() => $"I128({hi},{lo})"; + + public readonly struct BSATN : IReadWrite + { + public I128 Read(BinaryReader reader) => new(reader.ReadInt64(), reader.ReadUInt64()); + + public void Write(BinaryWriter writer, I128 value) + { + writer.Write(value.hi); + writer.Write(value.lo); + } + + public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => + new AlgebraicType.Builtin(new BuiltinType.I128(new Unit())); + } + } + + public struct U128 : IEquatable + { + public ulong hi; + public ulong lo; + + public U128(ulong hi, ulong lo) + { + this.lo = lo; + this.hi = hi; + } + + public readonly bool Equals(U128 x) => hi == x.hi && lo == x.lo; + + public override readonly bool Equals(object? o) => o is U128 x && Equals(x); + + public static bool operator ==(U128 a, U128 b) => a.Equals(b); + public static bool operator !=(U128 a, U128 b) => !a.Equals(b); + + public override readonly int GetHashCode() => hi.GetHashCode() ^ lo.GetHashCode(); + + public override readonly string ToString() => $"U128({hi},{lo})"; + + public readonly struct BSATN : IReadWrite + { + public U128 Read(BinaryReader reader) => new(reader.ReadUInt64(), reader.ReadUInt64()); + + public void Write(BinaryWriter writer, U128 value) + { + writer.Write(value.hi); + writer.Write(value.lo); + } + + public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => + new AlgebraicType.Builtin(new BuiltinType.U128(new Unit())); + } + } + +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs index d3f56f381ca..0d065d40658 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs @@ -12,16 +12,17 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class CallReducer { [DataMember(Name = "reducer")] public string Reducer = ""; + [DataMember(Name = "args")] public SpacetimeDB.ClientApi.EncodedValue Args = null!; + [DataMember(Name = "request_id")] public uint RequestId; - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs index 9cb1c4c7374..4badf680709 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs @@ -5,7 +5,6 @@ #nullable enable using System; -using SpacetimeDB; namespace SpacetimeDB.ClientApi { diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs index 245117ad702..0cf2567e4d9 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs @@ -12,12 +12,11 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class DatabaseUpdate { [DataMember(Name = "tables")] public System.Collections.Generic.List Tables = new(); - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs index ba142cb3385..7cd07b36fbe 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs @@ -12,12 +12,11 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class EnergyQuanta { [DataMember(Name = "quanta")] public U128 Quanta; - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs index 344cbbba87e..b1bbd183e20 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs @@ -12,16 +12,17 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class IdentityToken { [DataMember(Name = "identity")] public SpacetimeDB.Identity Identity = new(); + [DataMember(Name = "token")] public string Token = ""; + [DataMember(Name = "address")] public SpacetimeDB.Address Address = new(); - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs index 06ae7ba854e..ed704238c7f 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs @@ -12,16 +12,17 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class InitialSubscription { [DataMember(Name = "database_update")] public SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate = new(); + [DataMember(Name = "request_id")] public uint RequestId; + [DataMember(Name = "total_host_execution_duration_micros")] public ulong TotalHostExecutionDurationMicros; - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs index c103c829f52..c4625fe5450 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class OneOffQuery { [DataMember(Name = "message_id")] public byte[] MessageId = Array.Empty(); + [DataMember(Name = "query_string")] public string QueryString = ""; - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs index 35c1d0eb907..4e98289fca6 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs @@ -12,18 +12,20 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class OneOffQueryResponse { [DataMember(Name = "message_id")] public byte[] MessageId = Array.Empty(); + [DataMember(Name = "error")] public string? Error; + [DataMember(Name = "tables")] - public System.Collections.Generic.List Tables = new(); + public List Tables = new(); + [DataMember(Name = "total_host_execution_duration_micros")] public ulong TotalHostExecutionDurationMicros; - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs index 12f7e0f9d2b..84fa81bf6d2 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class OneOffTable { [DataMember(Name = "table_name")] public string TableName = ""; - [DataMember(Name = "rows")] - public System.Collections.Generic.List Rows = new(); + [DataMember(Name = "rows")] + public List Rows = new(); } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs index 44bc88654c5..86a67416429 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs @@ -12,18 +12,20 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class ReducerCallInfo { [DataMember(Name = "reducer_name")] public string ReducerName = ""; + [DataMember(Name = "reducer_id")] public uint ReducerId; + [DataMember(Name = "args")] public SpacetimeDB.ClientApi.EncodedValue Args = null!; + [DataMember(Name = "request_id")] public uint RequestId; - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs index 46b5be3adb7..7f4bf714e9a 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs @@ -5,7 +5,6 @@ #nullable enable using System; -using SpacetimeDB; namespace SpacetimeDB.ClientApi { diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs index d5eaba815a2..e844a34799c 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class Subscribe { [DataMember(Name = "query_strings")] public System.Collections.Generic.List QueryStrings = new(); + [DataMember(Name = "request_id")] public uint RequestId; - } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs index b9b47ea5d91..63400ee6a5d 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs @@ -12,18 +12,20 @@ namespace SpacetimeDB.ClientApi { - [SpacetimeDB.Type] [DataContract] + [SpacetimeDB.Type] public partial class TableUpdate { [DataMember(Name = "table_id")] public uint TableId; + [DataMember(Name = "table_name")] public string TableName = ""; + [DataMember(Name = "deletes")] - public System.Collections.Generic.List Deletes = new(); - [DataMember(Name = "inserts")] - public System.Collections.Generic.List Inserts = new(); + public List Deletes = new(); + [DataMember(Name = "inserts")] + public List Inserts = new(); } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs index fb71dd9e318..5861e9eef30 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs @@ -18,18 +18,23 @@ public partial class TransactionUpdate { [DataMember(Name = "status")] public SpacetimeDB.ClientApi.UpdateStatus Status = null!; + [DataMember(Name = "timestamp")] public SpacetimeDB.ClientApi.Timestamp Timestamp = new(); + [DataMember(Name = "caller_identity")] public SpacetimeDB.Identity CallerIdentity = new(); + [DataMember(Name = "caller_address")] public SpacetimeDB.Address CallerAddress = new(); + [DataMember(Name = "reducer_call")] public SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall = new(); + [DataMember(Name = "energy_quanta_used")] public SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed = new(); + [DataMember(Name = "host_execution_duration_micros")] public ulong HostExecutionDurationMicros; - } } diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index af4364c1d1d..8f722b3cfe0 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -43,15 +43,23 @@ class EnergyQuantaConverter : WriteOnlyJsonConverter { public override void Write(VerifyJsonWriter writer, EnergyQuanta value) { - writer.WriteRawValueIfNoStrict(value.Quanta.ToString()); + Assert.Equal(0uL, value.Quanta.hi); + writer.WriteValue(value.Quanta.lo); } } - class EncodedValueConverter : WriteOnlyJsonConverter + class EncodedValueConverter : WriteOnlyJsonConverter { - public override void Write(VerifyJsonWriter writer, EncodedValue.Binary value) + public override void Write(VerifyJsonWriter writer, EncodedValue value) { - writer.WriteValue(value.Binary_); + if (value is EncodedValue.Binary(var bytes)) + { + writer.WriteValue(bytes); + } + else + { + throw new InvalidOperationException(); + } } } diff --git a/sdks/csharp/tools/gen-client-api.bat b/sdks/csharp/tools/gen-client-api.bat deleted file mode 100644 index 9eb66c49cdc..00000000000 --- a/sdks/csharp/tools/gen-client-api.bat +++ /dev/null @@ -1,20 +0,0 @@ -@echo off -setlocal - -if "%CL_HOME%"=="" ( - echo "Variable CL_HOME not set" - exit /b 1 -) - -cd %CL_HOME%\SpacetimeDB\crates\client-api-messages -cargo run --example get_ws_schema > %CL_HOME%/schema.json - -cd %CL_HOME%\SpacetimeDB\crates\cli -cargo run -- generate -l csharp -n SpacetimeDB.ClientApi ^ - --json-module %CL_HOME%\schema.json ^ - -o %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi - -cd %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi -del /q _Globals - -del %CL_HOME%\schema.json diff --git a/sdks/csharp/tools/gen-client-api.sh b/sdks/csharp/tools/gen-client-api.sh deleted file mode 100644 index 91fbe3dab83..00000000000 --- a/sdks/csharp/tools/gen-client-api.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -eu -: $CL_HOME - -cd $CL_HOME/SpacetimeDB/crates/client-api-messages -cargo run --example get_ws_schema > $CL_HOME/schema.json - -cd $CL_HOME/SpacetimeDB/crates/cli -cargo run -- generate -l csharp -n SpacetimeDB.ClientApi \ - --json-module $CL_HOME/schema.json \ - -o $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi - -cd $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi -rm -rf _Globals - -rm -f $CL_HOME/schema.json From e57e5896cacf2bf283293f40e7ecb131fd5b18f2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 6 Aug 2024 21:06:17 +0200 Subject: [PATCH 106/223] Don't use BuiltinType.I/U128, use AlgebraicType.I/U128 (#116) ## Description of Changes Required to make "SDK Tests" pass in https://github.com/clockworklabs/SpacetimeDB/pull/1559. ## API Not breaking. ## Requires SpacetimeDB PRs - https://github.com/clockworklabs/SpacetimeDB/pull/1559 --------- Co-authored-by: Zeke Foppa --- sdks/csharp/src/Primitives.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/src/Primitives.cs b/sdks/csharp/src/Primitives.cs index 9466cca5711..93ba5e982ae 100644 --- a/sdks/csharp/src/Primitives.cs +++ b/sdks/csharp/src/Primitives.cs @@ -39,7 +39,7 @@ public void Write(BinaryWriter writer, I128 value) } public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.Builtin(new BuiltinType.I128(new Unit())); + new AlgebraicType.I128(new Unit()); } } @@ -76,7 +76,7 @@ public void Write(BinaryWriter writer, U128 value) } public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.Builtin(new BuiltinType.U128(new Unit())); + new AlgebraicType.U128(new Unit()); } } From 341be7f582d2a67a7a463af4cd1682e0fcee504e Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:28:53 -0700 Subject: [PATCH 107/223] Restore `dotnet pack` functionality (#118) ## Description of Changes Single-line change so that `dotnet pack` stops complaining that nothing was generated. Per @RReverser this brings this package more in line with our other C# packages. ## API Nah nothing breaking. ## Requires SpacetimeDB PRs Nope --------- Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 72a34580a96..058f8101089 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -5,7 +5,6 @@ 9 disable enable - True SpacetimeDB.ClientSDK SpacetimeDB SDK jdetter From 5670db6fe6346501544f7152363466f2e2fcef01 Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Wed, 7 Aug 2024 13:39:13 -0400 Subject: [PATCH 108/223] Update DEVELOP.md to reflect new codegen (#119) Also ran it again, committing a few generation changes too :) --- sdks/csharp/DEVELOP.md | 17 +++------------- .../src/SpacetimeDB/ClientApi/CallReducer.cs | 5 ++--- .../SpacetimeDB/ClientApi/ClientMessage.cs | 1 + .../SpacetimeDB/ClientApi/DatabaseUpdate.cs | 3 ++- .../src/SpacetimeDB/ClientApi/EnergyQuanta.cs | 3 ++- .../SpacetimeDB/ClientApi/IdentityToken.cs | 5 ++--- .../ClientApi/InitialSubscription.cs | 5 ++--- .../src/SpacetimeDB/ClientApi/OneOffQuery.cs | 4 ++-- .../ClientApi/OneOffQueryResponse.cs | 8 +++----- .../src/SpacetimeDB/ClientApi/OneOffTable.cs | 6 +++--- .../SpacetimeDB/ClientApi/ReducerCallInfo.cs | 6 ++---- .../SpacetimeDB/ClientApi/ServerMessage.cs | 1 + .../src/SpacetimeDB/ClientApi/Subscribe.cs | 4 ++-- .../src/SpacetimeDB/ClientApi/TableUpdate.cs | 10 ++++------ .../ClientApi/TransactionUpdate.cs | 7 +------ sdks/csharp/tools/gen-client-api.bat | 20 +++++++++++++++++++ sdks/csharp/tools/gen-client-api.sh | 15 ++++++++++++++ 17 files changed, 67 insertions(+), 53 deletions(-) create mode 100644 sdks/csharp/tools/gen-client-api.bat create mode 100644 sdks/csharp/tools/gen-client-api.sh diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index de08bc707b4..4f24f4d60cd 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -1,17 +1,6 @@ # Notes for maintainers -## `ClientApi.cs` +## `SpacetimeDB.ClientApi` -The file `ClientApi.cs` is generated by [ProtoBuf](https://protobuf.dev/) -from [the SpacetimeDB client-api-messages proto definition](https://github.com/clockworklabs/SpacetimeDB/blob/master/crates/client-api-messages/protobuf/client_api.proto). -This is not automated. -Whenever the `client_api.proto` changes, you'll have to manually re-run `protoc` to re-generate the definitions. - -```sh -cd ~/clockworklabs/SpacetimeDB/crates/client-api-messages/protobuf -protoc --csharp_out=/absolute/path/to/spacetimedb-csharp-sdk/src \ - ./client_api.proto -``` - -Note that `protoc` cannot understand paths that start with `~`; -you must write the absolute path starting from `/`. +To regenerate this namespace, run the `tools/gen-client-api.sh` or the +`tools/gen-client-api.bat` script. diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs index 0d065d40658..d3f56f381ca 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs @@ -12,17 +12,16 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class CallReducer { [DataMember(Name = "reducer")] public string Reducer = ""; - [DataMember(Name = "args")] public SpacetimeDB.ClientApi.EncodedValue Args = null!; - [DataMember(Name = "request_id")] public uint RequestId; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs index 4badf680709..9cb1c4c7374 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs @@ -5,6 +5,7 @@ #nullable enable using System; +using SpacetimeDB; namespace SpacetimeDB.ClientApi { diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs index 0cf2567e4d9..245117ad702 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs @@ -12,11 +12,12 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class DatabaseUpdate { [DataMember(Name = "tables")] public System.Collections.Generic.List Tables = new(); + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs index 7cd07b36fbe..ba142cb3385 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs @@ -12,11 +12,12 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class EnergyQuanta { [DataMember(Name = "quanta")] public U128 Quanta; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs index b1bbd183e20..344cbbba87e 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs @@ -12,17 +12,16 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class IdentityToken { [DataMember(Name = "identity")] public SpacetimeDB.Identity Identity = new(); - [DataMember(Name = "token")] public string Token = ""; - [DataMember(Name = "address")] public SpacetimeDB.Address Address = new(); + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs index ed704238c7f..06ae7ba854e 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs @@ -12,17 +12,16 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class InitialSubscription { [DataMember(Name = "database_update")] public SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate = new(); - [DataMember(Name = "request_id")] public uint RequestId; - [DataMember(Name = "total_host_execution_duration_micros")] public ulong TotalHostExecutionDurationMicros; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs index c4625fe5450..c103c829f52 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class OneOffQuery { [DataMember(Name = "message_id")] public byte[] MessageId = Array.Empty(); - [DataMember(Name = "query_string")] public string QueryString = ""; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs index 4e98289fca6..35c1d0eb907 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs @@ -12,20 +12,18 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class OneOffQueryResponse { [DataMember(Name = "message_id")] public byte[] MessageId = Array.Empty(); - [DataMember(Name = "error")] public string? Error; - [DataMember(Name = "tables")] - public List Tables = new(); - + public System.Collections.Generic.List Tables = new(); [DataMember(Name = "total_host_execution_duration_micros")] public ulong TotalHostExecutionDurationMicros; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs index 84fa81bf6d2..12f7e0f9d2b 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class OneOffTable { [DataMember(Name = "table_name")] public string TableName = ""; - [DataMember(Name = "rows")] - public List Rows = new(); + public System.Collections.Generic.List Rows = new(); + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs index 86a67416429..44bc88654c5 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs @@ -12,20 +12,18 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class ReducerCallInfo { [DataMember(Name = "reducer_name")] public string ReducerName = ""; - [DataMember(Name = "reducer_id")] public uint ReducerId; - [DataMember(Name = "args")] public SpacetimeDB.ClientApi.EncodedValue Args = null!; - [DataMember(Name = "request_id")] public uint RequestId; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs index 7f4bf714e9a..46b5be3adb7 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs @@ -5,6 +5,7 @@ #nullable enable using System; +using SpacetimeDB; namespace SpacetimeDB.ClientApi { diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs index e844a34799c..d5eaba815a2 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs @@ -12,14 +12,14 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class Subscribe { [DataMember(Name = "query_strings")] public System.Collections.Generic.List QueryStrings = new(); - [DataMember(Name = "request_id")] public uint RequestId; + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs index 63400ee6a5d..b9b47ea5d91 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs @@ -12,20 +12,18 @@ namespace SpacetimeDB.ClientApi { - [DataContract] [SpacetimeDB.Type] + [DataContract] public partial class TableUpdate { [DataMember(Name = "table_id")] public uint TableId; - [DataMember(Name = "table_name")] public string TableName = ""; - [DataMember(Name = "deletes")] - public List Deletes = new(); - + public System.Collections.Generic.List Deletes = new(); [DataMember(Name = "inserts")] - public List Inserts = new(); + public System.Collections.Generic.List Inserts = new(); + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs index 5861e9eef30..fb71dd9e318 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs @@ -18,23 +18,18 @@ public partial class TransactionUpdate { [DataMember(Name = "status")] public SpacetimeDB.ClientApi.UpdateStatus Status = null!; - [DataMember(Name = "timestamp")] public SpacetimeDB.ClientApi.Timestamp Timestamp = new(); - [DataMember(Name = "caller_identity")] public SpacetimeDB.Identity CallerIdentity = new(); - [DataMember(Name = "caller_address")] public SpacetimeDB.Address CallerAddress = new(); - [DataMember(Name = "reducer_call")] public SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall = new(); - [DataMember(Name = "energy_quanta_used")] public SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed = new(); - [DataMember(Name = "host_execution_duration_micros")] public ulong HostExecutionDurationMicros; + } } diff --git a/sdks/csharp/tools/gen-client-api.bat b/sdks/csharp/tools/gen-client-api.bat new file mode 100644 index 00000000000..9eb66c49cdc --- /dev/null +++ b/sdks/csharp/tools/gen-client-api.bat @@ -0,0 +1,20 @@ +@echo off +setlocal + +if "%CL_HOME%"=="" ( + echo "Variable CL_HOME not set" + exit /b 1 +) + +cd %CL_HOME%\SpacetimeDB\crates\client-api-messages +cargo run --example get_ws_schema > %CL_HOME%/schema.json + +cd %CL_HOME%\SpacetimeDB\crates\cli +cargo run -- generate -l csharp -n SpacetimeDB.ClientApi ^ + --json-module %CL_HOME%\schema.json ^ + -o %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi + +cd %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi +del /q _Globals + +del %CL_HOME%\schema.json diff --git a/sdks/csharp/tools/gen-client-api.sh b/sdks/csharp/tools/gen-client-api.sh new file mode 100644 index 00000000000..91fbe3dab83 --- /dev/null +++ b/sdks/csharp/tools/gen-client-api.sh @@ -0,0 +1,15 @@ +#!/bin/sh -eu +: $CL_HOME + +cd $CL_HOME/SpacetimeDB/crates/client-api-messages +cargo run --example get_ws_schema > $CL_HOME/schema.json + +cd $CL_HOME/SpacetimeDB/crates/cli +cargo run -- generate -l csharp -n SpacetimeDB.ClientApi \ + --json-module $CL_HOME/schema.json \ + -o $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi + +cd $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi +rm -rf _Globals + +rm -f $CL_HOME/schema.json From 2422b8cce17cf3c32ae162516b169035b9a06d4c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 13 Aug 2024 22:02:39 +0200 Subject: [PATCH 109/223] Nix `Primitives.cs` - types now defined in main repo (#120) ## Description of Changes These types have been moved to the main repo, where they are used by bindings-csharp as well. ## Requires SpacetimeDB PRs - https://github.com/clockworklabs/SpacetimeDB/pull/1477 --------- Co-authored-by: Ingvar Stepanyan Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 +- sdks/csharp/src/Primitives.cs | 83 ------------------------ sdks/csharp/tests~/SnapshotTests.cs | 16 ++--- 3 files changed, 6 insertions(+), 97 deletions(-) delete mode 100644 sdks/csharp/src/Primitives.cs diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 058f8101089..1c2158b20f7 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,7 +16,7 @@ logo.png README.md https://github.com/clockworklabs/spacetimedb-csharp-sdk - 0.11.0 + 0.12.0 $(AssemblyVersion) $(DefaultItemExcludes);*~/** @@ -24,7 +24,7 @@ - + diff --git a/sdks/csharp/src/Primitives.cs b/sdks/csharp/src/Primitives.cs deleted file mode 100644 index 93ba5e982ae..00000000000 --- a/sdks/csharp/src/Primitives.cs +++ /dev/null @@ -1,83 +0,0 @@ -using SpacetimeDB.BSATN; - -using System; -using System.IO; - -namespace SpacetimeDB -{ - - public struct I128 : IEquatable - { - public long hi; - public ulong lo; - - public I128(long hi, ulong lo) - { - this.hi = hi; - this.lo = lo; - } - - public readonly bool Equals(I128 x) => hi == x.hi && lo == x.lo; - - public override readonly bool Equals(object? o) => o is I128 x && Equals(x); - - public static bool operator ==(I128 a, I128 b) => a.Equals(b); - public static bool operator !=(I128 a, I128 b) => !a.Equals(b); - - public override readonly int GetHashCode() => hi.GetHashCode() ^ lo.GetHashCode(); - - public override readonly string ToString() => $"I128({hi},{lo})"; - - public readonly struct BSATN : IReadWrite - { - public I128 Read(BinaryReader reader) => new(reader.ReadInt64(), reader.ReadUInt64()); - - public void Write(BinaryWriter writer, I128 value) - { - writer.Write(value.hi); - writer.Write(value.lo); - } - - public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.I128(new Unit()); - } - } - - public struct U128 : IEquatable - { - public ulong hi; - public ulong lo; - - public U128(ulong hi, ulong lo) - { - this.lo = lo; - this.hi = hi; - } - - public readonly bool Equals(U128 x) => hi == x.hi && lo == x.lo; - - public override readonly bool Equals(object? o) => o is U128 x && Equals(x); - - public static bool operator ==(U128 a, U128 b) => a.Equals(b); - public static bool operator !=(U128 a, U128 b) => !a.Equals(b); - - public override readonly int GetHashCode() => hi.GetHashCode() ^ lo.GetHashCode(); - - public override readonly string ToString() => $"U128({hi},{lo})"; - - public readonly struct BSATN : IReadWrite - { - public U128 Read(BinaryReader reader) => new(reader.ReadUInt64(), reader.ReadUInt64()); - - public void Write(BinaryWriter writer, U128 value) - { - writer.Write(value.hi); - writer.Write(value.lo); - } - - public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => - new AlgebraicType.U128(new Unit()); - } - } - -} diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 8f722b3cfe0..af4364c1d1d 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -43,23 +43,15 @@ class EnergyQuantaConverter : WriteOnlyJsonConverter { public override void Write(VerifyJsonWriter writer, EnergyQuanta value) { - Assert.Equal(0uL, value.Quanta.hi); - writer.WriteValue(value.Quanta.lo); + writer.WriteRawValueIfNoStrict(value.Quanta.ToString()); } } - class EncodedValueConverter : WriteOnlyJsonConverter + class EncodedValueConverter : WriteOnlyJsonConverter { - public override void Write(VerifyJsonWriter writer, EncodedValue value) + public override void Write(VerifyJsonWriter writer, EncodedValue.Binary value) { - if (value is EncodedValue.Binary(var bytes)) - { - writer.WriteValue(bytes); - } - else - { - throw new InvalidOperationException(); - } + writer.WriteValue(value.Binary_); } } From 6312c455f3956c928f72a39be7fb09803ee0ffa9 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:27:55 -0700 Subject: [PATCH 110/223] Copy files from old repo (#127) ## Description of Changes For some reason, this repo was not quite properly synced up with the state of https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk-archive after https://github.com/clockworklabs/spacetimedb-csharp-sdk/pull/117. It's unclear to me how this happened, since the current state seems to be compatible with 0.11, but the [0.11 release commit/PR](https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk-archive/commit/382cce05fecbc00caf7c7d060fbde9a2854ad981) also bumped the `package.json` version, which didn't happen in this repo. I re-copied files over. Fortunately, the only real changes were to `package.json` and `README.md`. ## API No breaking changes. ## Requires SpacetimeDB PRs None Co-authored-by: Zeke Foppa --- sdks/csharp/README.md | 3 +-- sdks/csharp/package.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 189d6612894..18cb6f04172 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -6,10 +6,9 @@ This repository contains the [Unity](https://unity.com/) SDK for SpacetimeDB. Th ## Documentation -The Unity SDK uses the same code as the C# SDK. You can find the documentation for the C# SDK in the [C# SDK Reference](README.dotnet.md). +The Unity SDK uses the same code as the C# SDK. You can find the documentation for the C# SDK in the [C# SDK Reference](https://spacetimedb.com/docs/sdks/c-sharp) There is also a comprehensive Unity tutorial/demo available: - - [Unity Tutorial](https://spacetimedb.com/docs/unity/part-1) Doc - [Unity Demo](https://github.com/clockworklabs/SpacetimeDBUnityTutorial) Repo diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 8f6aa864f7a..86f04059235 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "0.10.0", + "version": "0.11.0", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From 589d40480f3a78280e51b987bb8cc33e85d36d2f Mon Sep 17 00:00:00 2001 From: SteveGibson <100594800+SteveBoytsun@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:52:50 -0400 Subject: [PATCH 111/223] Logging API (#132) ## Description of Changes *Describe what has been changed, any new features or bug fixes* Changed logging based on [this proposal](https://github.com/clockworklabs/SpacetimeDBPrivate/pull/981) ## API - [x] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* Logging interface is different now. `Logger` has been renamed to `Log`, and its methods have been renamed as well (ex. `Logger.LogError` is now `Log.Error`) ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --------- Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com> Co-authored-by: Zeke Foppa Co-authored-by: Jeremie Pelletier Co-authored-by: Steve Boytsun Co-authored-by: Ingvar Stepanyan --- .../.github/workflows/check-pr-base.yml | 22 ++++++++ sdks/csharp/DEVELOP.md | 4 +- sdks/csharp/src/ClientCache.cs | 6 +-- sdks/csharp/src/ConsoleLogger.cs | 52 ++++++++++++++----- sdks/csharp/src/ISpacetimeDBLogger.cs | 24 +++++---- sdks/csharp/src/SpacetimeDBClient.cs | 50 +++++++++--------- sdks/csharp/src/UnityDebugLogger.cs | 27 +++++++--- sdks/csharp/src/WebSocket.cs | 2 +- sdks/csharp/tests~/SnapshotTests.cs | 25 +++++++-- sdks/csharp/tools~/gen-client-api.bat | 20 +++++++ sdks/csharp/tools~/gen-client-api.sh | 15 ++++++ 11 files changed, 183 insertions(+), 64 deletions(-) create mode 100644 sdks/csharp/.github/workflows/check-pr-base.yml create mode 100644 sdks/csharp/tools~/gen-client-api.bat create mode 100644 sdks/csharp/tools~/gen-client-api.sh diff --git a/sdks/csharp/.github/workflows/check-pr-base.yml b/sdks/csharp/.github/workflows/check-pr-base.yml new file mode 100644 index 00000000000..73b71c27f0b --- /dev/null +++ b/sdks/csharp/.github/workflows/check-pr-base.yml @@ -0,0 +1,22 @@ +name: Git tree checks + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + merge_group: +permissions: read-all + +jobs: + check_base_ref: + name: Only release branches may merge into master + runs-on: ubuntu-latest + steps: + - id: not_based_on_master + if: | + github.event_name == 'pull_request' && + github.event.pull_request.base.ref == 'master' && + ! startsWith(github.event.pull_request.head.ref, 'release/') + run: | + echo 'Only `release/*` branches are allowed to merge into `master`.' + echo 'Maybe your PR should be merging into `staging`?' + exit 1 diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index 4f24f4d60cd..2b9ac7d98ae 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -2,5 +2,5 @@ ## `SpacetimeDB.ClientApi` -To regenerate this namespace, run the `tools/gen-client-api.sh` or the -`tools/gen-client-api.bat` script. +To regenerate this namespace, run the `tools~/gen-client-api.sh` or the +`tools~/gen-client-api.bat` script. diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index ec0a7212c4e..3b47f0fea04 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -44,7 +44,7 @@ public bool DeleteEntry(byte[] rowBytes) return true; } - Logger.LogWarning("Deleting value that we don't have (no cached value available)"); + Log.Warn("Deleting value that we don't have (no cached value available)"); return false; } @@ -65,7 +65,7 @@ public void AddTable() if (!tables.TryAdd(name, new TableCache())) { - Logger.LogError($"Table with name already exists: {name}"); + Log.Error($"Table with name already exists: {name}"); } } @@ -76,7 +76,7 @@ public void AddTable() return table; } - Logger.LogError($"We don't know that this table is: {name}"); + Log.Error($"We don't know that this table is: {name}"); return null; } diff --git a/sdks/csharp/src/ConsoleLogger.cs b/sdks/csharp/src/ConsoleLogger.cs index 08f2ce06779..1711899cf46 100644 --- a/sdks/csharp/src/ConsoleLogger.cs +++ b/sdks/csharp/src/ConsoleLogger.cs @@ -9,10 +9,12 @@ public enum LogLevel { None = 0, Debug = 1, - Warning = 2, - Error = 4, - Exception = 8, - All = Debug | Warning | Error | Exception + Trace = 2, + Info = 4, + Warning = 8, + Error = 16, + Exception = 32, + All = ~0 } LogLevel _logLevel; @@ -21,35 +23,59 @@ public ConsoleLogger(LogLevel logLevel = LogLevel.All) _logLevel = logLevel; } - public void Log(string message) + public void Debug(string message) { if (_logLevel.HasFlag(LogLevel.Debug)) { - Console.WriteLine(message); + Console.WriteLine($"[D] {message}"); } } - public void LogError(string message) + public void Trace(string message) + { + if (_logLevel.HasFlag(LogLevel.Trace)) + { + Console.WriteLine($"[T] {message}"); + } + } + + public void Info(string message) + { + if (_logLevel.HasFlag(LogLevel.Info)) + { + Console.WriteLine($"[I] {message}"); + } + } + + public void Warn(string message) + { + if (_logLevel.HasFlag(LogLevel.Warning)) + { + Console.WriteLine($"[W] {message}"); + } + } + + public void Error(string message) { if (_logLevel.HasFlag(LogLevel.Error)) { - Console.WriteLine($"Error: {message}"); + Console.WriteLine($"[E] {message}"); } } - public void LogException(Exception e) + public void Exception(string message) { if (_logLevel.HasFlag(LogLevel.Exception)) { - Console.WriteLine($"Exception: {e.Message}"); + Console.WriteLine($"[X] {message}"); } } - public void LogWarning(string message) + public void Exception(Exception exception) { - if (_logLevel.HasFlag(LogLevel.Warning)) + if (_logLevel.HasFlag(LogLevel.Exception)) { - Console.WriteLine($"Warning: {message}"); + Console.WriteLine($"[X] {exception}"); } } } diff --git a/sdks/csharp/src/ISpacetimeDBLogger.cs b/sdks/csharp/src/ISpacetimeDBLogger.cs index 33d99cdafef..5223a62868b 100644 --- a/sdks/csharp/src/ISpacetimeDBLogger.cs +++ b/sdks/csharp/src/ISpacetimeDBLogger.cs @@ -4,13 +4,16 @@ namespace SpacetimeDB { public interface ISpacetimeDBLogger { - void Log(string message); - void LogError(string message); - void LogWarning(string message); - void LogException(Exception e); + void Debug(string message); + void Trace(string message); + void Info(string message); + void Warn(string message); + void Error(string message); + void Exception(string message); + void Exception(Exception e); } - public static class Logger + public static class Log { public static ISpacetimeDBLogger Current = @@ -20,9 +23,12 @@ public static class Logger new ConsoleLogger(); #endif - public static void Log(string message) => Current.Log(message); - public static void LogError(string message) => Current.LogError(message); - public static void LogWarning(string message) => Current.LogWarning(message); - public static void LogException(Exception e) => Current.LogException(e); + public static void Debug(string message) => Current.Debug(message); + public static void Trace(string message) => Current.Trace(message); + public static void Info(string message) => Current.Info(message); + public static void Warn(string message) => Current.Warn(message); + public static void Error(string message) => Current.Error(message); + public static void Exception(string message) => Current.Exception(message); + public static void Exception(Exception exception) => Current.Exception(exception); } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index e0a9daa4f70..597735062bb 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -207,13 +207,13 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) var table = clientDB.GetTable(tableName); if (table == null) { - Logger.LogError($"Unknown table name: {tableName}"); + Log.Error($"Unknown table name: {tableName}"); continue; } if (update.Deletes.Count != 0) { - Logger.LogWarning("Non-insert during a subscription update!"); + Log.Warn("Non-insert during a subscription update!"); } var hashSet = GetInsertHashSet(table.ClientTableType, initialSubscription.DatabaseUpdate.Tables.Count); @@ -240,7 +240,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) break; case EncodedValue.Text(var txt): - Logger.LogWarning("JavaScript messages are unsupported."); + Log.Warn("JavaScript messages are unsupported."); break; } } @@ -261,7 +261,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) var table = clientDB.GetTable(tableName); if (table == null) { - Logger.LogError($"Unknown table name: {tableName}"); + Log.Error($"Unknown table name: {tableName}"); continue; } @@ -279,7 +279,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) { if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { - Logger.LogWarning($"Update with the same primary key was applied multiple times! tableName={tableName}"); + Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); // TODO(jdetter): Is this a correctable error? This would be a major error on the // SpacetimeDB side. continue; @@ -315,7 +315,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) { if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { - Logger.LogWarning($"Update with the same primary key was applied multiple times! tableName={tableName}"); + Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); // TODO(jdetter): Is this a correctable error? This would be a major error on the // SpacetimeDB side. continue; @@ -348,13 +348,13 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } break; case UpdateStatus.Failed(var failed): break; case UpdateStatus.OutOfEnergy(var outOfEnergy): - Logger.LogWarning("Failed to execute reducer: out of energy."); + Log.Warn("Failed to execute reducer: out of energy."); break; default: throw new InvalidOperationException(); @@ -368,7 +368,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) if (!waitingOneOffQueries.Remove(messageId, out var resultSource)) { - Logger.LogError($"Response to unknown one-off-query: {messageId}"); + Log.Error($"Response to unknown one-off-query: {messageId}"); break; } @@ -442,7 +442,7 @@ public void Connect(string? token, string uri, string addressOrName) uri = $"ws://{uri}"; } - Logger.Log($"SpacetimeDBClient: Connecting to {uri} {addressOrName}"); + Log.Info($"SpacetimeDBClient: Connecting to {uri} {addressOrName}"); Task.Run(async () => { try @@ -453,11 +453,11 @@ public void Connect(string? token, string uri, string addressOrName) { if (connectionClosed) { - Logger.Log("Connection closed gracefully."); + Log.Info("Connection closed gracefully."); return; } - Logger.LogException(e); + Log.Exception(e); } }); } @@ -476,7 +476,7 @@ private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List db } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } } } @@ -541,7 +541,7 @@ private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List db } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } } } @@ -566,7 +566,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } break; case ServerMessage.TransactionUpdate(var transactionUpdate): @@ -581,7 +581,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) var requestId = transactionUpdate.ReducerCall.RequestId; if (!stats.ReducerRequestTracker.FinishTrackingRequest(requestId)) { - Logger.LogWarning($"Failed to finish tracking reducer request: {requestId}"); + Log.Warn($"Failed to finish tracking reducer request: {requestId}"); } } OnMessageProcessCompleteUpdate(processed.reducerEvent, dbOps); @@ -591,7 +591,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } if (processed.reducerEvent is not { } reducerEvent) @@ -607,7 +607,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } if (!reducerFound && transactionUpdate.Status is UpdateStatus.Failed(var failed)) @@ -618,7 +618,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } } break; @@ -631,7 +631,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } break; case ServerMessage.OneOffQueryResponse: @@ -641,7 +641,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } catch (Exception e) { - Logger.LogException(e); + Log.Exception(e); } break; @@ -659,7 +659,7 @@ public void InternalCallReducer(T args) { if (!webSocket.IsConnected) { - Logger.LogError("Cannot call reducer, not connected to server!"); + Log.Error("Cannot call reducer, not connected to server!"); return; } @@ -677,7 +677,7 @@ public void Subscribe(List queries) { if (!webSocket.IsConnected) { - Logger.LogError("Cannot subscribe, not connected to server!"); + Log.Error("Cannot subscribe, not connected to server!"); return; } @@ -714,13 +714,13 @@ public async Task OneOffQuery(string query) if (!stats.OneOffRequestTracker.FinishTrackingRequest(requestId)) { - Logger.LogWarning($"Failed to finish tracking one off request: {requestId}"); + Log.Warn($"Failed to finish tracking one off request: {requestId}"); } T[] LogAndThrow(string error) { error = $"While processing one-off-query `{queryString}`, ID {messageId}: {error}"; - Logger.LogError(error); + Log.Error(error); throw new Exception(error); } diff --git a/sdks/csharp/src/UnityDebugLogger.cs b/sdks/csharp/src/UnityDebugLogger.cs index e78154bd9c9..114079f0688 100644 --- a/sdks/csharp/src/UnityDebugLogger.cs +++ b/sdks/csharp/src/UnityDebugLogger.cs @@ -10,25 +10,40 @@ namespace SpacetimeDB { public class UnityDebugLogger : ISpacetimeDBLogger { - public void Log(string message) + public void Debug(string message) { Debug.Log(message); } - public void LogError(string message) + public void Trace(string message) { - Debug.LogError(message); + Debug.Log(message); } - public void LogException(Exception e) + public void Info(string message) { - Debug.LogException(e); + Debug.Log(message); } - public void LogWarning(string message) + public void Warn(string message) { Debug.LogWarning(message); } + + public void Error(string message) + { + Debug.LogError(message); + } + + public void Exception(string message) + { + Debug.LogError(message); + } + + public void Exception(Exception e) + { + Debug.LogException(e); + } } } #endif diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 9944552888f..73d23e9a552 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -75,7 +75,7 @@ public async Task Connect(string? auth, string host, string nameOrAddress, Addre } catch (Exception ex) { - Logger.LogException(ex); + Log.Exception(ex); if (OnConnectError != null) { var message = ex.Message; diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index af4364c1d1d..8aeacaa3c0c 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -57,22 +57,37 @@ public override void Write(VerifyJsonWriter writer, EncodedValue.Binary value) class TestLogger(Events events) : ISpacetimeDBLogger { - public void Log(string message) + public void Debug(string message) + { + events.Add("Debug", message); + } + + public void Trace(string message) + { + events.Add("Trace", message); + } + + public void Info(string message) { events.Add("Log", message); } - public void LogWarning(string message) + public void Warn(string message) { events.Add("LogWarning", message); } - public void LogError(string message) + public void Error(string message) { events.Add("LogError", message); } - public void LogException(Exception e) + public void Exception(string message) + { + events.Add("LogException", message); + } + + public void Exception(Exception e) { events.Add("LogException", e.Message); } @@ -238,7 +253,7 @@ public async Task VerifyAllTablesParsed() { var events = new Events(); - Logger.Current = new TestLogger(events); + Log.Current = new TestLogger(events); var client = SpacetimeDBClient.instance; diff --git a/sdks/csharp/tools~/gen-client-api.bat b/sdks/csharp/tools~/gen-client-api.bat new file mode 100644 index 00000000000..9eb66c49cdc --- /dev/null +++ b/sdks/csharp/tools~/gen-client-api.bat @@ -0,0 +1,20 @@ +@echo off +setlocal + +if "%CL_HOME%"=="" ( + echo "Variable CL_HOME not set" + exit /b 1 +) + +cd %CL_HOME%\SpacetimeDB\crates\client-api-messages +cargo run --example get_ws_schema > %CL_HOME%/schema.json + +cd %CL_HOME%\SpacetimeDB\crates\cli +cargo run -- generate -l csharp -n SpacetimeDB.ClientApi ^ + --json-module %CL_HOME%\schema.json ^ + -o %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi + +cd %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi +del /q _Globals + +del %CL_HOME%\schema.json diff --git a/sdks/csharp/tools~/gen-client-api.sh b/sdks/csharp/tools~/gen-client-api.sh new file mode 100644 index 00000000000..91fbe3dab83 --- /dev/null +++ b/sdks/csharp/tools~/gen-client-api.sh @@ -0,0 +1,15 @@ +#!/bin/sh -eu +: $CL_HOME + +cd $CL_HOME/SpacetimeDB/crates/client-api-messages +cargo run --example get_ws_schema > $CL_HOME/schema.json + +cd $CL_HOME/SpacetimeDB/crates/cli +cargo run -- generate -l csharp -n SpacetimeDB.ClientApi \ + --json-module $CL_HOME/schema.json \ + -o $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi + +cd $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi +rm -rf _Globals + +rm -f $CL_HOME/schema.json From 76d30fedee66f8e69b6c18143aef99a1a02bb9df Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Mon, 30 Sep 2024 21:06:33 -0400 Subject: [PATCH 112/223] c# client SDK (DbConnection + SDK Callbacks) (#131) Implementation of the db connection proposal for C# --------- Co-authored-by: Ingvar Stepanyan --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 2 +- .../examples~/quickstart/client/Program.cs | 123 +++--- .../client/module_bindings/Message.cs | 28 +- .../module_bindings/SendMessageReducer.cs | 26 +- .../client/module_bindings/SetNameReducer.cs | 26 +- .../quickstart/client/module_bindings/User.cs | 42 +- .../_Globals/SpacetimeDBClient.cs | 164 ++++++-- .../examples~/quickstart/server/src/lib.rs | 18 +- sdks/csharp/src/ClientCache.cs | 36 +- sdks/csharp/src/Event.cs | 38 ++ .../{IDatabaseTable.cs.meta => Event.cs.meta} | 6 +- sdks/csharp/src/IDatabaseTable.cs | 82 ---- sdks/csharp/src/Primitives.cs.meta | 11 - sdks/csharp/src/SpacetimeDBClient.cs | 344 +++++++++------- sdks/csharp/src/Stubs.cs | 34 -- sdks/csharp/src/Table.cs | 72 ++++ .../src/{Stubs.cs.meta => Table.cs.meta} | 4 +- ...otTests.VerifyAllTablesParsed.verified.txt | 367 ++++++++++++------ sdks/csharp/tests~/SnapshotTests.cs | 45 ++- sdks/csharp/tests~/VerifyInit.cs | 2 - 20 files changed, 849 insertions(+), 621 deletions(-) create mode 100644 sdks/csharp/src/Event.cs rename sdks/csharp/src/{IDatabaseTable.cs.meta => Event.cs.meta} (65%) delete mode 100644 sdks/csharp/src/IDatabaseTable.cs delete mode 100644 sdks/csharp/src/Primitives.cs.meta delete mode 100644 sdks/csharp/src/Stubs.cs create mode 100644 sdks/csharp/src/Table.cs rename sdks/csharp/src/{Stubs.cs.meta => Table.cs.meta} (81%) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 1c2158b20f7..006a68bf0aa 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index 056d940e83b..7a1fb41245f 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -2,11 +2,17 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Net.WebSockets; using System.Threading; using SpacetimeDB; using SpacetimeDB.ClientApi; using SpacetimeDB.Types; +const string HOST = "http://localhost:3000"; +const string DBNAME = "chatqs"; + +DbConnection? conn = null; + // our local client SpacetimeDB identity Identity? local_identity = null; // declare a thread safe queue to store commands @@ -18,7 +24,25 @@ void Main() { AuthToken.Init(".spacetime_csharp_quickstart"); - RegisterCallbacks(); + conn = DbConnection.Builder() + .WithUri(HOST) + .WithModuleName(DBNAME) + //.WithCredentials((null, AuthToken.Token)) + .OnConnect(OnConnect) + .OnConnectError(OnConnectError) + .OnDisconnect(OnDisconnect) + .Build(); + + conn.RemoteTables.User.OnInsert += User_OnInsert; + conn.RemoteTables.User.OnUpdate += User_OnUpdate; + + conn.RemoteTables.Message.OnInsert += Message_OnInsert; + + conn.RemoteReducers.OnSetName += Reducer_OnSetNameEvent; + conn.RemoteReducers.OnSendMessage += Reducer_OnSendMessageEvent; + + conn.onSubscriptionApplied += OnSubscriptionApplied; + conn.onUnhandledReducerError += onUnhandledReducerError; // spawn a thread to call process updates and process commands var thread = new Thread(ProcessThread); @@ -31,25 +55,9 @@ void Main() thread.Join(); } -void RegisterCallbacks() -{ - SpacetimeDBClient.instance.onConnect += OnConnect; - SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; - SpacetimeDBClient.instance.onSubscriptionApplied += OnSubscriptionApplied; - SpacetimeDBClient.instance.onUnhandledReducerError += onUnhandledReducerError; - - User.OnInsert += User_OnInsert; - User.OnUpdate += User_OnUpdate; - - Message.OnInsert += Message_OnInsert; - - Reducer.OnSetNameEvent += Reducer_OnSetNameEvent; - Reducer.OnSendMessageEvent += Reducer_OnSendMessageEvent; -} - string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()[..8]; -void User_OnInsert(User insertedValue, ReducerEvent? dbEvent) +void User_OnInsert(EventContext ctx, User insertedValue) { if (insertedValue.Online) { @@ -57,7 +65,7 @@ void User_OnInsert(User insertedValue, ReducerEvent? dbEvent) } } -void User_OnUpdate(User oldValue, User newValue, ReducerEvent? dbEvent) +void User_OnUpdate(EventContext ctx, User oldValue, User newValue) { if (oldValue.Name != newValue.Name) { @@ -78,7 +86,7 @@ void User_OnUpdate(User oldValue, User newValue, ReducerEvent? dbEvent) void PrintMessage(Message message) { - var sender = User.FindByIdentity(message.Sender); + var sender = conn.RemoteTables.User.FindByIdentity(message.Sender); var senderName = "unknown"; if (sender != null) { @@ -88,44 +96,59 @@ void PrintMessage(Message message) Console.WriteLine($"{senderName}: {message.Text}"); } -void Message_OnInsert(Message insertedValue, ReducerEvent? dbEvent) +void Message_OnInsert(EventContext ctx, Message insertedValue) { - if (dbEvent != null) + if (ctx.Reducer is not Event.SubscribeApplied) { PrintMessage(insertedValue); } } -void Reducer_OnSetNameEvent(ReducerEvent reducerEvent, string name) +void Reducer_OnSetNameEvent(EventContext ctx, string name) { - if (reducerEvent.Identity == local_identity && reducerEvent.Status is UpdateStatus.Failed) + if (ctx.Reducer is Event.Reducer reducer) { - Console.Write($"Failed to change name to {name}"); + var e = reducer.ReducerEvent; + if (e.CallerIdentity == local_identity && e.Status is Status.Failed(var error)) + { + Console.Write($"Failed to change name to {name}: {error}"); + } } } -void Reducer_OnSendMessageEvent(ReducerEvent reducerEvent, string text) +void Reducer_OnSendMessageEvent(EventContext ctx, string text) { - if (reducerEvent.Identity == local_identity && reducerEvent.Status is UpdateStatus.Failed) + if (ctx.Reducer is Event.Reducer reducer) { - Console.Write($"Failed to send message {text}"); + var e = reducer.ReducerEvent; + if (e.CallerIdentity == local_identity && e.Status is Status.Failed(var error)) + { + Console.Write($"Failed to send message {text}: {error}"); + } } } -void OnConnect() +void OnConnect(Identity identity, string authToken) { - SpacetimeDBClient.instance.Subscribe(new List { "SELECT * FROM User", "SELECT * FROM Message" }); + local_identity = identity; + AuthToken.SaveToken(authToken); + + conn!.Subscribe(new List { "SELECT * FROM User", "SELECT * FROM Message" }); } -void OnIdentityReceived(string authToken, Identity identity, Address _address) +void OnConnectError(WebSocketError? error, string message) { - local_identity = identity; - AuthToken.SaveToken(authToken); + +} + +void OnDisconnect(DbConnection conn, WebSocketCloseStatus? status, WebSocketError? error) +{ + } void PrintMessagesInOrder() { - foreach (Message message in Message.Iter().OrderBy(item => item.Sent)) + foreach (Message message in conn.RemoteTables.Message.Iter().OrderBy(item => item.Sent)) { PrintMessage(message); } @@ -137,29 +160,29 @@ void OnSubscriptionApplied() PrintMessagesInOrder(); } -void onUnhandledReducerError(ReducerEvent reducerEvent) +void onUnhandledReducerError(ReducerEvent reducerEvent) { - Console.WriteLine($"Unhandled reducer error in {reducerEvent.ReducerName}: {reducerEvent.ErrMessage}"); + Console.WriteLine($"Unhandled reducer error in {reducerEvent.Reducer}: {reducerEvent.Status}"); } -const string HOST = "http://localhost:3000"; -const string DBNAME = "chatqs"; - void ProcessThread() { - SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME); - - // loop until cancellation token - while (!cancel_token.IsCancellationRequested) + try { - SpacetimeDBClient.instance.Update(); + // loop until cancellation token + while (!cancel_token.IsCancellationRequested) + { + conn.Update(); - ProcessCommands(); + ProcessCommands(); - Thread.Sleep(100); + Thread.Sleep(100); + } + } + finally + { + conn.Close(); } - - SpacetimeDBClient.instance.Close(); } void InputLoop() @@ -192,10 +215,10 @@ void ProcessCommands() switch (command.Command) { case "message": - Reducer.SendMessage(command.Args); + conn.RemoteReducers.SendMessage(command.Args); break; case "name": - Reducer.SetName(command.Args); + conn.RemoteReducers.SetName(command.Args); break; } } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs index 4676194ec9e..c0e52cf0e1a 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs @@ -14,30 +14,30 @@ namespace SpacetimeDB.Types { [SpacetimeDB.Type] [DataContract] - public partial class Message : SpacetimeDB.DatabaseTable + public partial class Message : IDatabaseRow { [DataMember(Name = "sender")] - public SpacetimeDB.Identity Sender = new(); + public SpacetimeDB.Identity Sender; [DataMember(Name = "sent")] public ulong Sent; [DataMember(Name = "text")] - public string Text = ""; + public string Text; - public static IEnumerable FilterBySender(SpacetimeDB.Identity value) + public Message( + SpacetimeDB.Identity Sender, + ulong Sent, + string Text + ) { - return Query(x => x.Sender == value); + this.Sender = Sender; + this.Sent = Sent; + this.Text = Text; } - public static IEnumerable FilterBySent(ulong value) + public Message() { - return Query(x => x.Sent == value); + this.Sender = new(); + this.Text = ""; } - - public static IEnumerable FilterByText(string value) - { - return Query(x => x.Text == value); - } - - } } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs index ffb537b63c5..45dd29f339e 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs @@ -12,32 +12,8 @@ namespace SpacetimeDB.Types [SpacetimeDB.Type] public partial class SendMessageArgsStruct : IReducerArgs { - ReducerType IReducerArgs.ReducerType => ReducerType.SendMessage; - string IReducerArgsBase.ReducerName => "send_message"; - bool IReducerArgs.InvokeHandler(ReducerEvent reducerEvent) => Reducer.OnSendMessage(reducerEvent, this); + string IReducerArgs.ReducerName => "send_message"; public string Text = ""; } - - public static partial class Reducer - { - public delegate void SendMessageHandler(ReducerEvent reducerEvent, string text); - public static event SendMessageHandler? OnSendMessageEvent; - - public static void SendMessage(string text) - { - SpacetimeDBClient.instance.InternalCallReducer(new SendMessageArgsStruct { Text = text }); - } - - public static bool OnSendMessage(ReducerEvent reducerEvent, SendMessageArgsStruct args) - { - if (OnSendMessageEvent == null) return false; - OnSendMessageEvent( - reducerEvent, - args.Text - ); - return true; - } - } - } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs index bdc3efd2578..0f96ad9e1f6 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs @@ -12,32 +12,8 @@ namespace SpacetimeDB.Types [SpacetimeDB.Type] public partial class SetNameArgsStruct : IReducerArgs { - ReducerType IReducerArgs.ReducerType => ReducerType.SetName; - string IReducerArgsBase.ReducerName => "set_name"; - bool IReducerArgs.InvokeHandler(ReducerEvent reducerEvent) => Reducer.OnSetName(reducerEvent, this); + string IReducerArgs.ReducerName => "set_name"; public string Name = ""; } - - public static partial class Reducer - { - public delegate void SetNameHandler(ReducerEvent reducerEvent, string name); - public static event SetNameHandler? OnSetNameEvent; - - public static void SetName(string name) - { - SpacetimeDBClient.instance.InternalCallReducer(new SetNameArgsStruct { Name = name }); - } - - public static bool OnSetName(ReducerEvent reducerEvent, SetNameArgsStruct args) - { - if (OnSetNameEvent == null) return false; - OnSetNameEvent( - reducerEvent, - args.Name - ); - return true; - } - } - } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs index 94442532629..a6d6d1b9b30 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs @@ -14,47 +14,29 @@ namespace SpacetimeDB.Types { [SpacetimeDB.Type] [DataContract] - public partial class User : SpacetimeDB.DatabaseTableWithPrimaryKey + public partial class User : IDatabaseRow { [DataMember(Name = "identity")] - public SpacetimeDB.Identity Identity = new(); + public SpacetimeDB.Identity Identity; [DataMember(Name = "name")] public string? Name; [DataMember(Name = "online")] public bool Online; - private static Dictionary Identity_Index = new(16); - - public override void InternalOnValueInserted() - { - Identity_Index[Identity] = this; - } - - public override void InternalOnValueDeleted() - { - Identity_Index.Remove(Identity); - } - - public static User? FindByIdentity(SpacetimeDB.Identity value) - { - Identity_Index.TryGetValue(value, out var r); - return r; - } - - public static IEnumerable FilterByIdentity(SpacetimeDB.Identity value) + public User( + SpacetimeDB.Identity Identity, + string? Name, + bool Online + ) { - if (FindByIdentity(value) is {} found) - { - yield return found; - } + this.Identity = Identity; + this.Name = Name; + this.Online = Online; } - public static IEnumerable FilterByOnline(bool value) + public User() { - return Query(x => x.Online == value); + this.Identity = new(); } - - public override object GetPrimaryKeyValue() => Identity; - } } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs index 49dae53e43a..270481a2511 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs @@ -5,64 +5,158 @@ #nullable enable using System; -using SpacetimeDB; +using System.Collections.Generic; + using SpacetimeDB.ClientApi; namespace SpacetimeDB.Types { - public enum ReducerType + public sealed class RemoteTables { - None, - SendMessage, - SetName, - } + public class MessageHandle : RemoteTableHandle { + public IEnumerable FilterBySender(SpacetimeDB.Identity value) { + return Query(x => x.Sender == value); + } - public interface IReducerArgs : IReducerArgsBase - { - ReducerType ReducerType { get; } - bool InvokeHandler(ReducerEvent reducerEvent); + public IEnumerable FilterBySent(ulong value) { + return Query(x => x.Sent == value); + } + + public IEnumerable FilterByText(string value) { + return Query(x => x.Text == value); + } + } + + public class UserHandle : RemoteTableHandle { + public override object? GetPrimaryKey(IDatabaseRow row) => ((User)row).Identity; + + private Dictionary Identity_Index = new(16); + + public override void InternalInvokeValueInserted(IDatabaseRow row) { + var value = (User)row; + Identity_Index[value.Identity] = value; + } + + public override void InternalInvokeValueDeleted(IDatabaseRow row) { + Identity_Index.Remove(((User)row).Identity); + } + + public User? FindByIdentity(SpacetimeDB.Identity value) { + Identity_Index.TryGetValue(value, out var r); + return r; + } + + public IEnumerable FilterByIdentity(SpacetimeDB.Identity value) { + if (FindByIdentity(value) is { } found) { + yield return found; + } + } + + public IEnumerable FilterByOnline(bool value) { + return Query(x => x.Online == value); + } + } + + public readonly MessageHandle Message = new(); + public readonly UserHandle User = new(); } - public partial class ReducerEvent : ReducerEventBase + public sealed class RemoteReducers : RemoteBase { - public IReducerArgs? Args { get; } + internal RemoteReducers(DbConnection conn) : base(conn) {} - public string ReducerName => Args?.ReducerName ?? ""; + public delegate void SendMessageHandler(EventContext ctx, string text); + public event SendMessageHandler? OnSendMessage; - [Obsolete("ReducerType is deprecated, please match directly on type of .Args instead.")] - public ReducerType Reducer => Args?.ReducerType ?? ReducerType.None; + public void SendMessage(string text) + { + conn.InternalCallReducer(new SendMessageArgsStruct { Text = text }); + } - public ReducerEvent(IReducerArgs? args) : base() => Args = args; - public ReducerEvent(TransactionUpdate dbEvent, IReducerArgs? args) : base(dbEvent) => Args = args; + public bool InvokeSendMessage(EventContext ctx, SendMessageArgsStruct args) + { + if (OnSendMessage == null) return false; + OnSendMessage( + ctx, + args.Text + ); + return true; + } + public delegate void SetNameHandler(EventContext ctx, string name); + public event SetNameHandler? OnSetName; - [Obsolete("Accessors that implicitly cast `Args` are deprecated, please match `Args` against the desired type explicitly instead.")] - public SendMessageArgsStruct SendMessageArgs => (SendMessageArgsStruct)Args!; - [Obsolete("Accessors that implicitly cast `Args` are deprecated, please match `Args` against the desired type explicitly instead.")] - public SetNameArgsStruct SetNameArgs => (SetNameArgsStruct)Args!; + public void SetName(string name) + { + conn.InternalCallReducer(new SetNameArgsStruct { Name = name }); + } + + public bool InvokeSetName(EventContext ctx, SetNameArgsStruct args) + { + if (OnSetName == null) return false; + OnSetName( + ctx, + args.Name + ); + return true; + } + } + + public partial record EventContext : DbContext, IEventContext { + public readonly RemoteReducers Reducers; + public readonly Event Reducer; - public override bool InvokeHandler() => Args?.InvokeHandler(this) ?? false; + internal EventContext(DbConnection conn, Event reducer) : base(conn.RemoteTables) { + Reducers = conn.RemoteReducers; + Reducer = reducer; + } } - public class SpacetimeDBClient : SpacetimeDBClientBase + [Type] + public partial record Reducer : TaggedEnum<( + SendMessageArgsStruct SendMessage, + SetNameArgsStruct SetName, + Unit IdentityConnected, + Unit IdentityDisconnected + )>; + + public class DbConnection : DbConnectionBase { - protected SpacetimeDBClient() + public readonly RemoteTables RemoteTables = new(); + public readonly RemoteReducers RemoteReducers; + + public DbConnection() { - clientDB.AddTable(); - clientDB.AddTable(); - } + RemoteReducers = new(this); - public static readonly SpacetimeDBClient instance = new(); + clientDB.AddTable("Message", RemoteTables.Message); + clientDB.AddTable("User", RemoteTables.User); + } - protected override ReducerEvent ReducerEventFromDbEvent(TransactionUpdate update) + protected override Reducer ToReducer(TransactionUpdate update) { - var argBytes = update.ReducerCall.Args; - IReducerArgs? args = update.ReducerCall.ReducerName switch { - "send_message" => BSATNHelpers.Decode(argBytes), - "set_name" => BSATNHelpers.Decode(argBytes), - "" => null, + var encodedArgs = update.ReducerCall.Args; + return update.ReducerCall.ReducerName switch { + "send_message" => new Reducer.SendMessage(BSATNHelpers.Decode(encodedArgs)), + "set_name" => new Reducer.SetName(BSATNHelpers.Decode(encodedArgs)), + "__identity_connected__" => new Reducer.IdentityConnected(default), + "__identity_disconnected__" => new Reducer.IdentityDisconnected(default), var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; - return new ReducerEvent(update, args); + } + + protected override IEventContext ToEventContext(Event reducerEvent) { + return new EventContext(this, reducerEvent); + } + + protected override bool Dispatch(IEventContext context, Reducer reducer) { + var eventContext = (EventContext)context; + return reducer switch { + Reducer.SendMessage(var args) => RemoteReducers.InvokeSendMessage(eventContext, args), + Reducer.SetName(var args) => RemoteReducers.InvokeSetName(eventContext, args), + Reducer.IdentityConnected => true, + Reducer.IdentityDisconnected => true, + _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; } } } diff --git a/sdks/csharp/examples~/quickstart/server/src/lib.rs b/sdks/csharp/examples~/quickstart/server/src/lib.rs index d47c6592b4f..0c6572e1975 100644 --- a/sdks/csharp/examples~/quickstart/server/src/lib.rs +++ b/sdks/csharp/examples~/quickstart/server/src/lib.rs @@ -1,27 +1,27 @@ -use spacetimedb::{spacetimedb, ReducerContext, Identity, Timestamp}; +use spacetimedb::{ReducerContext, Identity, Timestamp}; use anyhow::{Result, anyhow}; -#[spacetimedb(table(public))] +#[spacetimedb::table(name = User, public)] pub struct User { - #[primarykey] + #[primary_key] identity: Identity, name: Option, online: bool, } -#[spacetimedb(table(public))] +#[spacetimedb::table(name = Message, public)] pub struct Message { sender: Identity, sent: Timestamp, text: String, } -#[spacetimedb(init)] +#[spacetimedb::reducer(init)] pub fn init() { // Called when the module is initially published } -#[spacetimedb(connect)] +#[spacetimedb::reducer(client_connected)] pub fn identity_connected(ctx: ReducerContext) { if let Some(user) = User::filter_by_identity(&ctx.sender) { // If this is a returning user, i.e. we already have a `User` with this `Identity`, @@ -38,7 +38,7 @@ pub fn identity_connected(ctx: ReducerContext) { } } -#[spacetimedb(disconnect)] +#[spacetimedb::reducer(client_disconnected)] pub fn identity_disconnected(ctx: ReducerContext) { if let Some(user) = User::filter_by_identity(&ctx.sender) { User::update_by_identity(&ctx.sender, User { online: false, ..user }); @@ -57,7 +57,7 @@ fn validate_name(name: String) -> Result { } } -#[spacetimedb(reducer)] +#[spacetimedb::reducer] pub fn set_name(ctx: ReducerContext, name: String) -> Result<()> { let name = validate_name(name)?; if let Some(user) = User::filter_by_identity(&ctx.sender) { @@ -76,7 +76,7 @@ fn validate_message(text: String) -> Result { } } -#[spacetimedb(reducer)] +#[spacetimedb::reducer] pub fn send_message(ctx: ReducerContext, text: String) -> Result<()> { // Things to consider: // - Rate-limit messages per-user. diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 3b47f0fea04..9992f0cbf7f 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -2,27 +2,31 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using SpacetimeDB.BSATN; using SpacetimeDB.Internal; namespace SpacetimeDB { public class ClientCache { - public interface ITableCache : IEnumerable> + public interface ITableCache : IEnumerable> { Type ClientTableType { get; } - bool InsertEntry(byte[] rowBytes, IDatabaseTable value); + bool InsertEntry(byte[] rowBytes, IDatabaseRow value); bool DeleteEntry(byte[] rowBytes); - IDatabaseTable DecodeValue(byte[] bytes); + IDatabaseRow DecodeValue(byte[] bytes); + IRemoteTableHandle Handle { get; } } - public class TableCache : ITableCache - where T : IDatabaseTable, IStructuralReadWrite, new() + public class TableCache : ITableCache + where Row : IDatabaseRow, new() { - public Type ClientTableType => typeof(T); + public TableCache(IRemoteTableHandle handle) => Handle = handle; - public static readonly Dictionary Entries = new(ByteArrayComparer.Instance); + public IRemoteTableHandle Handle { get; init; } + + public Type ClientTableType => typeof(Row); + + public readonly Dictionary Entries = new(ByteArrayComparer.Instance); /// /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. @@ -30,7 +34,7 @@ public class TableCache : ITableCache /// The BSATN encoded bytes of the row to retrieve. /// The parsed row encoded by the rowBytes. /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. - public bool InsertEntry(byte[] rowBytes, IDatabaseTable value) => Entries.TryAdd(rowBytes, (T)value); + public bool InsertEntry(byte[] rowBytes, IDatabaseRow value) => Entries.TryAdd(rowBytes, (Row)value); /// /// Deletes a value from the table. @@ -49,21 +53,21 @@ public bool DeleteEntry(byte[] rowBytes) } // The function to use for decoding a type value. - public IDatabaseTable DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); + public IDatabaseRow DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); - public IEnumerator> GetEnumerator() => Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)).GetEnumerator(); + public IEnumerator> GetEnumerator() => Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } private readonly Dictionary tables = new(); - public void AddTable() - where T : IDatabaseTable, IStructuralReadWrite, new() + public void AddTable(string name, IRemoteTableHandle handle) + where Row : IDatabaseRow, new() { - string name = typeof(T).Name; - - if (!tables.TryAdd(name, new TableCache())) + var cache = new TableCache(handle); + handle.SetCache(cache); + if (!tables.TryAdd(name, cache)) { Log.Error($"Table with name already exists: {name}"); } diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs new file mode 100644 index 00000000000..131cf3f77a8 --- /dev/null +++ b/sdks/csharp/src/Event.cs @@ -0,0 +1,38 @@ +using System; + +namespace SpacetimeDB +{ + public interface IEventContext { } + + public interface IReducerArgs : BSATN.IStructuralReadWrite + { + string ReducerName { get; } + } + + [Type] + public partial record Status : TaggedEnum<( + Unit Committed, + string Failed, + Unit OutOfEnergy + )>; + + public record ReducerEvent( + DateTimeOffset Timestamp, + Status Status, + Identity CallerIdentity, + Address? CallerAddress, + U128? EnergyConsumed, + R Reducer + ); + + public record Event + { + private Event() { } + + public record Reducer(ReducerEvent ReducerEvent) : Event; + public record SubscribeApplied : Event; + public record UnsubscribeApplied : Event; + public record SubscribeError(Exception Exception) : Event; + public record UnknownTransaction : Event; + } +} \ No newline at end of file diff --git a/sdks/csharp/src/IDatabaseTable.cs.meta b/sdks/csharp/src/Event.cs.meta similarity index 65% rename from sdks/csharp/src/IDatabaseTable.cs.meta rename to sdks/csharp/src/Event.cs.meta index a32271541b4..c1de34211ca 100644 --- a/sdks/csharp/src/IDatabaseTable.cs.meta +++ b/sdks/csharp/src/Event.cs.meta @@ -1,5 +1,5 @@ -fileFormatVersion: 2 -guid: 11f729b0583a241499850598f6d9c870 +fileFormatVersion: 2 +guid: 3c8f2bbd66a24c0f8710b2825daeba1d MonoImporter: externalObjects: {} serializedVersion: 2 @@ -8,4 +8,4 @@ MonoImporter: icon: {instanceID: 0} userData: assetBundleName: - assetBundleVariant: + assetBundleVariant: \ No newline at end of file diff --git a/sdks/csharp/src/IDatabaseTable.cs b/sdks/csharp/src/IDatabaseTable.cs deleted file mode 100644 index a028771a794..00000000000 --- a/sdks/csharp/src/IDatabaseTable.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using SpacetimeDB.BSATN; - -namespace SpacetimeDB -{ - public interface IDatabaseTable - { - void InternalOnValueInserted(); - void InternalOnValueDeleted(); - void OnInsertEvent(ReducerEventBase? update); - void OnBeforeDeleteEvent(ReducerEventBase? update); - void OnDeleteEvent(ReducerEventBase? update); - } - - public abstract class DatabaseTable : IDatabaseTable - where T : DatabaseTable, IStructuralReadWrite, new() - where ReducerEvent : ReducerEventBase - { - public virtual void InternalOnValueInserted() { } - - public virtual void InternalOnValueDeleted() { } - - public static IEnumerable Iter() - { - return ClientCache.TableCache.Entries.Values; - } - - public static IEnumerable Query(Func filter) - { - return Iter().Where(filter); - } - - public static int Count() - { - return ClientCache.TableCache.Entries.Count; - } - - public delegate void InsertEventHandler(T insertedValue, ReducerEvent? dbEvent); - public delegate void DeleteEventHandler(T deletedValue, ReducerEvent? dbEvent); - public static event InsertEventHandler? OnInsert; - public static event DeleteEventHandler? OnBeforeDelete; - public static event DeleteEventHandler? OnDelete; - - public void OnInsertEvent(ReducerEventBase? dbEvent) - { - OnInsert?.Invoke((T)this, (ReducerEvent?)dbEvent); - } - - public void OnBeforeDeleteEvent(ReducerEventBase? dbEvent) - { - OnBeforeDelete?.Invoke((T)this, (ReducerEvent?)dbEvent); - } - - public void OnDeleteEvent(ReducerEventBase? dbEvent) - { - OnDelete?.Invoke((T)this, (ReducerEvent?)dbEvent); - } - } - - public interface IDatabaseTableWithPrimaryKey : IDatabaseTable - { - void OnUpdateEvent(IDatabaseTableWithPrimaryKey newValue, ReducerEventBase? update); - object GetPrimaryKeyValue(); - } - - public abstract class DatabaseTableWithPrimaryKey : DatabaseTable, IDatabaseTableWithPrimaryKey - where T : DatabaseTableWithPrimaryKey, IStructuralReadWrite, new() - where ReducerEvent : ReducerEventBase - { - public abstract object GetPrimaryKeyValue(); - - public delegate void UpdateEventHandler(T oldValue, T newValue, ReducerEvent? update); - public static event UpdateEventHandler? OnUpdate; - - public void OnUpdateEvent(IDatabaseTableWithPrimaryKey newValue, ReducerEventBase? dbEvent) - { - OnUpdate?.Invoke((T)this, (T)newValue, (ReducerEvent?)dbEvent); - } - } -} diff --git a/sdks/csharp/src/Primitives.cs.meta b/sdks/csharp/src/Primitives.cs.meta deleted file mode 100644 index 3ed18da1cbe..00000000000 --- a/sdks/csharp/src/Primitives.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 565602d5968368295b6cf26721a8890a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 597735062bb..932cf5b907e 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -11,18 +11,83 @@ using SpacetimeDB.Internal; using SpacetimeDB.ClientApi; using Thread = System.Threading.Thread; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("SpacetimeDB.Tests")] namespace SpacetimeDB { - public abstract class SpacetimeDBClientBase - where ReducerEvent : ReducerEventBase + public sealed class DbConnectionBuilder + where DbConnection : DbConnectionBase, new() { + readonly DbConnection conn = new(); + + string? uri; + string? nameOrAddress; + string? token; + + public DbConnection Build() + { + if (uri == null) + { + throw new InvalidOperationException("Building DbConnection with a null uri. Call WithUri() first."); + } + if (nameOrAddress == null) + { + throw new InvalidOperationException("Building DbConnection with a null nameOrAddress. Call WithModuleName() first."); + } + conn.Connect(token, uri, nameOrAddress); + return conn; + } + + public DbConnectionBuilder WithUri(string uri) + { + this.uri = uri; + return this; + } + + public DbConnectionBuilder WithModuleName(string nameOrAddress) + { + this.nameOrAddress = nameOrAddress; + return this; + } + + public DbConnectionBuilder WithCredentials(in (Identity identity, string token)? creds) + { + token = creds?.token; + return this; + } + + public DbConnectionBuilder OnConnect(Action cb) + { + conn.onConnect += cb; + return this; + } + + public DbConnectionBuilder OnConnectError(Action cb) + { + conn.webSocket.OnConnectError += (a, b) => cb.Invoke(a, b); + return this; + } + + public DbConnectionBuilder OnDisconnect(Action cb) + { + conn.webSocket.OnClose += (code, error) => cb.Invoke(conn, code, error); + return this; + } + } + + public abstract class DbConnectionBase + where DbConnection : DbConnectionBase, new() + { + public static DbConnectionBuilder Builder() => new(); + struct DbValue { - public IDatabaseTable value; + public IDatabaseRow value; public byte[] bytes; - public DbValue(IDatabaseTable value, byte[] bytes) + public DbValue(IDatabaseRow value, byte[] bytes) { this.value = value; this.bytes = bytes; @@ -36,26 +101,13 @@ struct DbOp public DbValue? insert; } - /// - /// Called when a connection is established to a spacetimedb instance. - /// - public event Action? onConnect; - - /// - /// Called when a connection attempt fails. - /// - public event Action? onConnectError; + internal event Action? onConnect; /// /// Called when an exception occurs when sending a message. /// public event Action? onSendError; - /// - /// Called when a connection that was established has disconnected. - /// - public event Action? onDisconnect; - /// /// Invoked when a subscription is about to start being processed. This is called even before OnBeforeDelete. /// @@ -69,12 +121,7 @@ struct DbOp /// /// Invoked when a reducer is returned with an error and has no client-side handler. /// - public event Action? onUnhandledReducerError; - - /// - /// Called when we receive an identity from the server - /// - public event Action? onIdentityReceived; + public event Action>? onUnhandledReducerError; /// /// Invoked when an event message is received or at the end of a transaction update. @@ -84,11 +131,12 @@ struct DbOp public readonly Address clientAddress = Address.Random(); public Identity? clientIdentity { get; private set; } - private SpacetimeDB.WebSocket webSocket; + internal WebSocket webSocket; private bool connectionClosed; protected readonly ClientCache clientDB = new(); - protected abstract ReducerEvent ReducerEventFromDbEvent(TransactionUpdate dbEvent); + protected abstract Reducer ToReducer(TransactionUpdate update); + protected abstract IEventContext ToEventContext(Event reducerEvent); private readonly Dictionary> waitingOneOffQueries = new(); @@ -96,7 +144,7 @@ struct DbOp private readonly Thread networkMessageProcessThread; public readonly Stats stats = new(); - protected SpacetimeDBClientBase() + protected DbConnectionBase() { var options = new ConnectOptions { @@ -106,9 +154,6 @@ protected SpacetimeDBClientBase() }; webSocket = new WebSocket(options); webSocket.OnMessage += OnMessageReceived; - webSocket.OnClose += (code, error) => onDisconnect?.Invoke(code, error); - webSocket.OnConnect += () => onConnect?.Invoke(); - webSocket.OnConnectError += (a, b) => onConnectError?.Invoke(a, b); webSocket.OnSendError += a => onSendError?.Invoke(a); networkMessageProcessThread = new Thread(PreProcessMessages); @@ -126,7 +171,7 @@ struct ProcessedMessage public ServerMessage message; public List dbOps; public DateTime timestamp; - public ReducerEvent? reducerEvent; + public ReducerEvent? reducerEvent; } struct PreProcessedMessage @@ -153,6 +198,9 @@ struct PreProcessedMessage _ => throw new InvalidOperationException(), }; + private static readonly Status Committed = new Status.Committed(default); + private static readonly Status OutOfEnergy = new Status.OutOfEnergy(default); + void PreProcessMessages() { while (!isClosing) @@ -177,7 +225,7 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) using var binaryReader = new BinaryReader(decompressedStream); var message = new ServerMessage.BSATN().Read(binaryReader); - ReducerEvent? reducerEvent = null; + ReducerEvent? reducerEvent = default; // This is all of the inserts Dictionary>? subscriptionInserts = null; @@ -245,119 +293,121 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) } } } - break; case ServerMessage.TransactionUpdate(var transactionUpdate): - switch (transactionUpdate.Status) + // Convert the generic event arguments in to a domain specific event object + try + { + reducerEvent = new( + DateTimeOffset.FromUnixTimeMilliseconds((long)transactionUpdate.Timestamp.Microseconds / 1000), + transactionUpdate.Status switch + { + UpdateStatus.Committed => Committed, + UpdateStatus.OutOfEnergy => OutOfEnergy, + UpdateStatus.Failed(var reason) => new Status.Failed(reason), + _ => throw new InvalidOperationException() + }, + transactionUpdate.CallerIdentity, + transactionUpdate.CallerAddress, + transactionUpdate.EnergyQuantaUsed.Quanta, + ToReducer(transactionUpdate)); + } + catch (Exception e) + { + Log.Exception(e); + } + + if (transactionUpdate.Status is UpdateStatus.Committed(var committed)) { - case UpdateStatus.Committed(var committed): - primaryKeyChanges = new(); + primaryKeyChanges = new(); - // First apply all of the state - foreach (var update in committed.Tables) + // First apply all of the state + foreach (var update in committed.Tables) + { + var tableName = update.TableName; + var table = clientDB.GetTable(tableName); + if (table == null) { - var tableName = update.TableName; - var table = clientDB.GetTable(tableName); - if (table == null) - { - Log.Error($"Unknown table name: {tableName}"); - continue; - } + Log.Error($"Unknown table name: {tableName}"); + continue; + } - foreach (var row in update.Inserts) + foreach (var row in update.Inserts) + { + var op = new DbOp { table = table, insert = Decode(table, row) }; + var pk = table.Handle.GetPrimaryKey(op.insert.Value.value); + if (pk != null) { - var op = new DbOp { table = table, insert = Decode(table, row) }; + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, pk); - if (op.insert.Value.value is IDatabaseTableWithPrimaryKey objWithPk) + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { - // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, objWithPk.GetPrimaryKeyValue()); - - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) - { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; - } - - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - op = new DbOp - { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; + Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. + continue; } - primaryKeyChanges[key] = op; - } - else - { - dbOps.Add(op); + + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + op = new DbOp + { + table = insertOp.table, + delete = deleteOp.delete, + insert = insertOp.insert, + }; } + primaryKeyChanges[key] = op; + } + else + { + dbOps.Add(op); } + } - foreach (var row in update.Deletes) + foreach (var row in update.Deletes) + { + var op = new DbOp { table = table, delete = Decode(table, row) }; + var pk = table.Handle.GetPrimaryKey(op.delete.Value.value); + if (pk != null) { - var op = new DbOp { table = table, delete = Decode(table, row) }; + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, pk); - if (op.delete.Value.value is IDatabaseTableWithPrimaryKey objWithPk) + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { - // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, objWithPk.GetPrimaryKeyValue()); - - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) - { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; - } - - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - op = new DbOp - { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; + Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. + continue; } - primaryKeyChanges[key] = op; - } - else - { - dbOps.Add(op); + + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + op = new DbOp + { + table = insertOp.table, + delete = deleteOp.delete, + insert = insertOp.insert, + }; } + primaryKeyChanges[key] = op; + } + else + { + dbOps.Add(op); } } + } - // Combine primary key updates and non-primary key updates - dbOps.AddRange(primaryKeyChanges.Values); - - // Convert the generic event arguments in to a domain specific event object - try - { - reducerEvent = ReducerEventFromDbEvent(transactionUpdate); - } - catch (Exception e) - { - Log.Exception(e); - } - break; - case UpdateStatus.Failed(var failed): - break; - case UpdateStatus.OutOfEnergy(var outOfEnergy): - Log.Warn("Failed to execute reducer: out of energy."); - break; - default: - throw new InvalidOperationException(); + // Combine primary key updates and non-primary key updates + dbOps.AddRange(primaryKeyChanges.Values); } break; case ServerMessage.IdentityToken(var identityToken): @@ -462,8 +512,7 @@ public void Connect(string? token, string uri, string addressOrName) }); } - - private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List dbOps) + private void OnMessageProcessCompleteUpdate(IEventContext eventContext, List dbOps) { // First trigger OnBeforeDelete foreach (var update in dbOps) @@ -472,7 +521,7 @@ private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List db { try { - oldValue.OnBeforeDeleteEvent(dbEvent!); + update.table.Handle.InvokeBeforeDelete(eventContext, oldValue); } catch (Exception e) { @@ -491,7 +540,7 @@ private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List db { if (update.table.DeleteEntry(delete.bytes)) { - delete.value.InternalOnValueDeleted(); + update.table.Handle.InternalInvokeValueDeleted(delete.value); } else { @@ -504,7 +553,7 @@ private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List db { if (update.table.InsertEntry(insert.bytes, insert.value)) { - insert.value.InternalOnValueInserted(); + update.table.Handle.InternalInvokeValueInserted(insert.value); } else { @@ -523,19 +572,16 @@ private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List db { case { insert: { value: var newValue }, delete: { value: var oldValue } }: { - // If we matched an update, these values must have primary keys. - var newValue_ = (IDatabaseTableWithPrimaryKey)newValue; - var oldValue_ = (IDatabaseTableWithPrimaryKey)oldValue; - oldValue_.OnUpdateEvent(newValue_, dbEvent); + dbOp.table.Handle.InvokeUpdate(eventContext, oldValue, newValue); break; } case { insert: { value: var newValue } }: - newValue.OnInsertEvent(dbEvent); + dbOp.table.Handle.InvokeInsert(eventContext, newValue); break; case { delete: { value: var oldValue } }: - oldValue.OnDeleteEvent(dbEvent); + dbOp.table.Handle.InvokeDelete(eventContext, oldValue); break; } } @@ -546,6 +592,8 @@ private void OnMessageProcessCompleteUpdate(ReducerEvent? dbEvent, List db } } + protected abstract bool Dispatch(IEventContext context, Reducer reducer); + private void OnMessageProcessComplete(PreProcessedMessage preProcessed) { var processed = CalculateStateDiff(preProcessed); @@ -559,7 +607,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) onBeforeSubscriptionApplied?.Invoke(); stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.InitialSubscription)}"); stats.SubscriptionRequestTracker.FinishTrackingRequest(initialSubscription.RequestId); - OnMessageProcessCompleteUpdate(null, dbOps); + OnMessageProcessCompleteUpdate(ToEventContext(new Event.SubscribeApplied()), dbOps); try { onSubscriptionApplied?.Invoke(); @@ -569,6 +617,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) Log.Exception(e); } break; + case ServerMessage.TransactionUpdate(var transactionUpdate): var reducer = transactionUpdate.ReducerCall.ReducerName; stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdate)},reducer={reducer}"); @@ -584,7 +633,15 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) Log.Warn($"Failed to finish tracking reducer request: {requestId}"); } } - OnMessageProcessCompleteUpdate(processed.reducerEvent, dbOps); + + if (processed.reducerEvent is not { } reducerEvent) + { + // If we are here, an error about unknown reducer should have already been logged, so nothing to do. + break; + } + + var eventContext = ToEventContext(new Event.Reducer(reducerEvent)); + OnMessageProcessCompleteUpdate(eventContext, dbOps); try { onEvent?.Invoke(message); @@ -594,16 +651,10 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) Log.Exception(e); } - if (processed.reducerEvent is not { } reducerEvent) - { - // If we are here, an error about unknown reducer should have already been logged, so nothing to do. - break; - } - var reducerFound = false; try { - reducerFound = reducerEvent.InvokeHandler(); + reducerFound = Dispatch(eventContext, reducerEvent.Reducer); } catch (Exception e) { @@ -622,18 +673,19 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } } break; + case ServerMessage.IdentityToken(var identityToken): try { clientIdentity = identityToken.Identity; - var address = identityToken.Address; - onIdentityReceived?.Invoke(identityToken.Token, clientIdentity, address); + onConnect?.Invoke(identityToken.Identity, identityToken.Token); } catch (Exception e) { Log.Exception(e); } break; + case ServerMessage.OneOffQueryResponse: try { @@ -643,8 +695,8 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) { Log.Exception(e); } - break; + default: throw new InvalidOperationException(); } @@ -655,7 +707,7 @@ internal void OnMessageReceived(byte[] bytes, DateTime timestamp) => _messageQueue.Add(new UnprocessedMessage { bytes = bytes, timestamp = timestamp }); public void InternalCallReducer(T args) - where T : IReducerArgsBase, new() + where T : IReducerArgs, new() { if (!webSocket.IsConnected) { @@ -691,7 +743,7 @@ public void Subscribe(List queries) /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("WHERE sender = \"bob\""); public async Task OneOffQuery(string query) - where T : IDatabaseTable, IStructuralReadWrite, new() + where T : IDatabaseRow, new() { var messageId = Guid.NewGuid(); var type = typeof(T); diff --git a/sdks/csharp/src/Stubs.cs b/sdks/csharp/src/Stubs.cs deleted file mode 100644 index f9ba62020d3..00000000000 --- a/sdks/csharp/src/Stubs.cs +++ /dev/null @@ -1,34 +0,0 @@ -using SpacetimeDB.ClientApi; - -namespace SpacetimeDB -{ - public interface IReducerArgsBase : BSATN.IStructuralReadWrite - { - string ReducerName { get; } - } - - public abstract class ReducerEventBase - { - public ulong Timestamp { get; } - public Identity? Identity { get; } - public Address? CallerAddress { get; } - public string? ErrMessage { get; } - public UpdateStatus? Status { get; } - - public ReducerEventBase() { } - - public ReducerEventBase(TransactionUpdate update) - { - Timestamp = update.Timestamp.Microseconds; - Identity = update.CallerIdentity; - CallerAddress = update.CallerAddress; - Status = update.Status; - if (update.Status is UpdateStatus.Failed(var err)) - { - ErrMessage = err; - } - } - - public abstract bool InvokeHandler(); - } -} diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs new file mode 100644 index 00000000000..b2764028ac4 --- /dev/null +++ b/sdks/csharp/src/Table.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using SpacetimeDB.BSATN; + +namespace SpacetimeDB +{ + public interface IDatabaseRow : IStructuralReadWrite { } + + public abstract class RemoteBase + { + protected readonly DbConnection conn; + + protected RemoteBase(DbConnection conn) + { + this.conn = conn; + } + } + + public interface IRemoteTableHandle + { + void SetCache(ClientCache.ITableCache cache); + + object? GetPrimaryKey(IDatabaseRow row); + + void InternalInvokeValueInserted(IDatabaseRow row); + void InternalInvokeValueDeleted(IDatabaseRow row); + void InvokeInsert(IEventContext context, IDatabaseRow row); + void InvokeDelete(IEventContext context, IDatabaseRow row); + void InvokeBeforeDelete(IEventContext context, IDatabaseRow row); + void InvokeUpdate(IEventContext context, IDatabaseRow oldRow, IDatabaseRow newRow); + } + + public abstract class RemoteTableHandle : IRemoteTableHandle + where EventContext : class, IEventContext + where Row : IDatabaseRow, new() + { + public void SetCache(ClientCache.ITableCache cache) => Cache = (ClientCache.TableCache)cache; + + internal ClientCache.TableCache? Cache; + + public event Action? OnInsert; + public event Action? OnDelete; + public event Action? OnBeforeDelete; + public event Action? OnUpdate; + + public virtual object? GetPrimaryKey(IDatabaseRow row) => null; + + public virtual void InternalInvokeValueInserted(IDatabaseRow row) { } + + public virtual void InternalInvokeValueDeleted(IDatabaseRow row) { } + + public int Count => Cache!.Entries.Count; + + public IEnumerable Iter() => Cache!.Entries.Values; + + public IEnumerable Query(Func filter) => Iter().Where(filter); + + public void InvokeInsert(IEventContext context, IDatabaseRow row) => + OnInsert?.Invoke((EventContext)context, (Row)row); + + public void InvokeDelete(IEventContext context, IDatabaseRow row) => + OnDelete?.Invoke((EventContext)context, (Row)row); + + public void InvokeBeforeDelete(IEventContext context, IDatabaseRow row) => + OnBeforeDelete?.Invoke((EventContext)context, (Row)row); + + public void InvokeUpdate(IEventContext context, IDatabaseRow oldRow, IDatabaseRow newRow) => + OnUpdate?.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); + } +} \ No newline at end of file diff --git a/sdks/csharp/src/Stubs.cs.meta b/sdks/csharp/src/Table.cs.meta similarity index 81% rename from sdks/csharp/src/Stubs.cs.meta rename to sdks/csharp/src/Table.cs.meta index da0198c0c84..09681bfa3f0 100644 --- a/sdks/csharp/src/Stubs.cs.meta +++ b/sdks/csharp/src/Table.cs.meta @@ -1,4 +1,4 @@ -fileFormatVersion: 2 +fileFormatVersion: 2 guid: 0de7dc78e75a21a428bfa6e3dd520ba9 MonoImporter: externalObjects: {} @@ -8,4 +8,4 @@ MonoImporter: icon: {instanceID: 0} userData: assetBundleName: - assetBundleVariant: + assetBundleVariant: \ No newline at end of file diff --git a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt index 12aa9234c77..fd948740840 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -1,17 +1,33 @@ { Events: { - OnIdentityReceived: { - identity: Identity_1, - address: Guid_1 - }, + OnIdentityReceived: Identity_1, OnInsertUser: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: {}, + Db: {Scrubbed} + }, user: { identity: Identity_1, online: true } }, - LogException: Unknown reducer __identity_connected__ (Parameter 'Reducer'), + LogException: Unknown reducer unknown-reducer (Parameter 'Reducer'), OnInsertUser: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_1, + Status: {}, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: {} + } + }, + Db: {Scrubbed} + }, user: { identity: Identity_2, online: true @@ -20,8 +36,8 @@ OnEvent: { status: {Scrubbed}, timestamp: 1718487763059031, - caller_identity: {Scrubbed}, - caller_address: Guid_2, + caller_identity: Identity_2, + caller_address: Guid_1, reducer_call: { reducer_name: __identity_connected__, args: @@ -30,6 +46,24 @@ host_execution_duration_micros: 66 }, OnUpdateUser: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_2, + Status: {}, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + SetName_: { + Name: A + } + } + } + }, + Db: {Scrubbed} + }, oldUser: { identity: Identity_1, online: true @@ -38,22 +72,13 @@ identity: Identity_1, name: A, online: true - }, - reducerEvent: { - Args: { - Name: A - }, - Timestamp: 1718487768057579, - Identity: Identity_1, - CallerAddress: Guid_1, - Status: {Scrubbed} } }, OnEvent: { status: {Scrubbed}, timestamp: 1718487768057579, - caller_identity: {Scrubbed}, - caller_address: Guid_1, + caller_identity: Identity_1, + caller_address: Guid_2, reducer_call: { reducer_name: set_name, args: AQAAAEE=, @@ -63,35 +88,53 @@ host_execution_duration_micros: 70 }, OnSetName: { - Args: { - Name: A + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_2, + Status: {}, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + SetName_: { + Name: A + } + } + } }, - Timestamp: 1718487768057579, - Identity: Identity_1, - CallerAddress: Guid_1, - Status: {Scrubbed} + Db: {Scrubbed} }, OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_3, + Status: {}, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + SendMessage_: { + Text: Hello, A! + } + } + } + }, + Db: {Scrubbed} + }, message: { sender: Identity_2, sent: 1718487775346381, text: Hello, A! - }, - reducerEvent: { - Args: { - Text: Hello, A! - }, - Timestamp: 1718487775346381, - Identity: Identity_2, - CallerAddress: Guid_2, - Status: {Scrubbed} } }, OnEvent: { status: {Scrubbed}, timestamp: 1718487775346381, - caller_identity: {Scrubbed}, - caller_address: Guid_2, + caller_identity: Identity_2, + caller_address: Guid_1, reducer_call: { reducer_name: send_message, args: CQAAAEhlbGxvLCBBIQ==, @@ -101,15 +144,42 @@ host_execution_duration_micros: 57 }, OnSendMessage: { - Args: { - Text: Hello, A! + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_3, + Status: {}, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + SendMessage_: { + Text: Hello, A! + } + } + } }, - Timestamp: 1718487775346381, - Identity: Identity_2, - CallerAddress: Guid_2, - Status: {Scrubbed} + Db: {Scrubbed} }, OnUpdateUser: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_4, + Status: {}, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + SetName_: { + Name: B + } + } + } + }, + Db: {Scrubbed} + }, oldUser: { identity: Identity_2, online: true @@ -118,22 +188,13 @@ identity: Identity_2, name: B, online: true - }, - reducerEvent: { - Args: { - Name: B - }, - Timestamp: 1718487777307855, - Identity: Identity_2, - CallerAddress: Guid_2, - Status: {Scrubbed} } }, OnEvent: { status: {Scrubbed}, timestamp: 1718487777307855, - caller_identity: {Scrubbed}, - caller_address: Guid_2, + caller_identity: Identity_2, + caller_address: Guid_1, reducer_call: { reducer_name: set_name, args: AQAAAEI=, @@ -143,35 +204,53 @@ host_execution_duration_micros: 98 }, OnSetName: { - Args: { - Name: B + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_4, + Status: {}, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + SetName_: { + Name: B + } + } + } }, - Timestamp: 1718487777307855, - Identity: Identity_2, - CallerAddress: Guid_2, - Status: {Scrubbed} + Db: {Scrubbed} }, OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_5, + Status: {}, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + SendMessage_: { + Text: Hello, B! + } + } + } + }, + Db: {Scrubbed} + }, message: { sender: Identity_1, sent: 1718487783175083, text: Hello, B! - }, - reducerEvent: { - Args: { - Text: Hello, B! - }, - Timestamp: 1718487783175083, - Identity: Identity_1, - CallerAddress: Guid_1, - Status: {Scrubbed} } }, OnEvent: { status: {Scrubbed}, timestamp: 1718487783175083, - caller_identity: {Scrubbed}, - caller_address: Guid_1, + caller_identity: Identity_1, + caller_address: Guid_2, reducer_call: { reducer_name: send_message, args: CQAAAEhlbGxvLCBCIQ==, @@ -181,35 +260,53 @@ host_execution_duration_micros: 40 }, OnSendMessage: { - Args: { - Text: Hello, B! + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_5, + Status: {}, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + SendMessage_: { + Text: Hello, B! + } + } + } }, - Timestamp: 1718487783175083, - Identity: Identity_1, - CallerAddress: Guid_1, - Status: {Scrubbed} + Db: {Scrubbed} }, OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_6, + Status: {}, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + SendMessage_: { + Text: Goodbye! + } + } + } + }, + Db: {Scrubbed} + }, message: { sender: Identity_2, sent: 1718487787645364, text: Goodbye! - }, - reducerEvent: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487787645364, - Identity: Identity_2, - CallerAddress: Guid_2, - Status: {Scrubbed} } }, OnEvent: { status: {Scrubbed}, timestamp: 1718487787645364, - caller_identity: {Scrubbed}, - caller_address: Guid_2, + caller_identity: Identity_2, + caller_address: Guid_1, reducer_call: { reducer_name: send_message, args: CAAAAEdvb2RieWUh, @@ -219,16 +316,38 @@ host_execution_duration_micros: 28 }, OnSendMessage: { - Args: { - Text: Goodbye! + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_6, + Status: {}, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + SendMessage_: { + Text: Goodbye! + } + } + } }, - Timestamp: 1718487787645364, - Identity: Identity_2, - CallerAddress: Guid_2, - Status: {Scrubbed} + Db: {Scrubbed} }, - LogException: Unknown reducer __identity_disconnected__ (Parameter 'Reducer'), OnUpdateUser: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_7, + Status: {}, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: {} + } + }, + Db: {Scrubbed} + }, oldUser: { identity: Identity_2, name: B, @@ -243,8 +362,8 @@ OnEvent: { status: {Scrubbed}, timestamp: 1718487791901504, - caller_identity: {Scrubbed}, - caller_address: Guid_2, + caller_identity: Identity_2, + caller_address: Guid_1, reducer_call: { reducer_name: __identity_disconnected__, args: @@ -253,26 +372,35 @@ host_execution_duration_micros: 75 }, OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_8, + Status: {}, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + SendMessage_: { + Text: Goodbye! + } + } + } + }, + Db: {Scrubbed} + }, message: { sender: Identity_1, sent: 1718487794937841, text: Goodbye! - }, - reducerEvent: { - Args: { - Text: Goodbye! - }, - Timestamp: 1718487794937841, - Identity: Identity_1, - CallerAddress: Guid_1, - Status: {Scrubbed} } }, OnEvent: { status: {Scrubbed}, timestamp: 1718487794937841, - caller_identity: {Scrubbed}, - caller_address: Guid_1, + caller_identity: Identity_1, + caller_address: Guid_2, reducer_call: { reducer_name: send_message, args: CAAAAEdvb2RieWUh, @@ -282,13 +410,22 @@ host_execution_duration_micros: 34 }, OnSendMessage: { - Args: { - Text: Goodbye! + Reducers: {Scrubbed}, + Reducer: { + ReducerEvent: { + Timestamp: DateTimeOffset_8, + Status: {}, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + SendMessage_: { + Text: Goodbye! + } + } + } }, - Timestamp: 1718487794937841, - Identity: Identity_1, - CallerAddress: Guid_1, - Status: {Scrubbed} + Db: {Scrubbed} } }, FinalSnapshot: { @@ -330,7 +467,7 @@ Stats: { ReducerRequestTracker: { sampleCount: 3, - requestsAwaitingResponse: 5, + requestsAwaitingResponse: 6, Min: sample#4, Max: sample#2 }, @@ -341,12 +478,12 @@ Max: sample#1 }, AllReducersTracker: { - sampleCount: 8, + sampleCount: 9, Min: reducer=send_message, Max: reducer=set_name }, ParseMessageTracker: { - sampleCount: 9, + sampleCount: 10, Min: type=TransactionUpdate,reducer=send_message, Max: type=InitialSubscription } diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 8aeacaa3c0c..72486fa632f 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -206,6 +206,9 @@ private static ServerMessage[] SampleDump() => [ SampleSubscriptionUpdate( 1, 366, [SampleUserInsert("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true)] ), + SampleTransactionUpdate(0, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "unknown-reducer", 0, 40, [], null + ), SampleTransactionUpdate( 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", 0, "__identity_connected__", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], @@ -255,7 +258,7 @@ public async Task VerifyAllTablesParsed() Log.Current = new TestLogger(events); - var client = SpacetimeDBClient.instance; + var client = new DbConnection(); var sampleDumpParsed = SampleDump(); @@ -292,35 +295,35 @@ public async Task VerifyAllTablesParsed() ServerMessage.OneOffQueryResponse(var o) => o, _ => throw new InvalidOperationException() }); - client.onIdentityReceived += (_authToken, identity, address) => - events.Add("OnIdentityReceived", new { identity, address }); + client.onConnect += (identity, _token) => + events.Add("OnIdentityReceived", identity); client.onSubscriptionApplied += () => events.Add("OnSubscriptionApplied"); client.onUnhandledReducerError += (exception) => events.Add("OnUnhandledReducerError", exception); - Reducer.OnSendMessageEvent += (reducerEvent, _text) => - events.Add("OnSendMessage", reducerEvent); - Reducer.OnSetNameEvent += (reducerEvent, _name) => events.Add("OnSetName", reducerEvent); + client.RemoteReducers.OnSendMessage += (eventContext, _text) => + events.Add("OnSendMessage", eventContext); + client.RemoteReducers.OnSetName += (eventContext, _name) => events.Add("OnSetName", eventContext); - User.OnDelete += (user, reducerEvent) => - events.Add("OnDeleteUser", new { user, reducerEvent }); - User.OnInsert += (user, reducerEvent) => - events.Add("OnInsertUser", new { user, reducerEvent }); - User.OnUpdate += (oldUser, newUser, reducerEvent) => + client.RemoteTables.User.OnDelete += (eventContext, user) => + events.Add("OnDeleteUser", new { eventContext, user }); + client.RemoteTables.User.OnInsert += (eventContext, user) => + events.Add("OnInsertUser", new { eventContext, user }); + client.RemoteTables.User.OnUpdate += (eventContext, oldUser, newUser) => events.Add( "OnUpdateUser", new { + eventContext, oldUser, - newUser, - reducerEvent + newUser } ); - Message.OnDelete += (message, reducerEvent) => - events.Add("OnDeleteMessage", new { message, reducerEvent }); - Message.OnInsert += (message, reducerEvent) => - events.Add("OnInsertMessage", new { message, reducerEvent }); + client.RemoteTables.Message.OnDelete += (eventContext, message) => + events.Add("OnDeleteMessage", new { eventContext, message }); + client.RemoteTables.Message.OnInsert += (eventContext, message) => + events.Add("OnInsertMessage", new { eventContext, message }); // Simulate receiving WebSocket messages. foreach (var sample in sampleDumpBinary) @@ -340,8 +343,8 @@ await Verify( Events = events, FinalSnapshot = new { - User = User.Iter().ToList(), - Message = Message.Iter().ToList() + User = client.RemoteTables.User.Iter().ToList(), + Message = client.RemoteTables.Message.Iter().ToList() }, Stats = client.stats } @@ -352,8 +355,8 @@ await Verify( new EnergyQuantaConverter(), new EncodedValueConverter() ])) - .ScrubMember(x => x.CallerIdentity) .ScrubMember(x => x.Status) - .ScrubMember(x => x.Status); + .ScrubMember>(x => x.Db) + .ScrubMember(x => x.Reducers); } } diff --git a/sdks/csharp/tests~/VerifyInit.cs b/sdks/csharp/tests~/VerifyInit.cs index bc75d5e5805..58d37d65965 100644 --- a/sdks/csharp/tests~/VerifyInit.cs +++ b/sdks/csharp/tests~/VerifyInit.cs @@ -81,7 +81,5 @@ public static void Init() ] ) ); - - VerifierSettings.IgnoreMember(_ => _.ReducerName); } } From 5c033a4e4db2daa2e175e51d117f158b621cb64e Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 1 Oct 2024 17:17:45 +0100 Subject: [PATCH 113/223] Subscription API (#137) ## Description of Changes Implements the subscription builder (at least, the parts that are possible to implement). ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- .../examples~/quickstart/client/Program.cs | 57 ++++--- .../_Globals/SpacetimeDBClient.cs | 2 + sdks/csharp/src/Event.cs | 60 +++++++- sdks/csharp/src/SpacetimeDBClient.cs | 143 ++++++++++-------- sdks/csharp/tests~/SnapshotTests.cs | 1 - 5 files changed, 170 insertions(+), 93 deletions(-) diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index 7a1fb41245f..cd378c594d2 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -5,30 +5,29 @@ using System.Net.WebSockets; using System.Threading; using SpacetimeDB; -using SpacetimeDB.ClientApi; using SpacetimeDB.Types; const string HOST = "http://localhost:3000"; const string DBNAME = "chatqs"; -DbConnection? conn = null; - // our local client SpacetimeDB identity Identity? local_identity = null; // declare a thread safe queue to store commands var input_queue = new ConcurrentQueue<(string Command, string Args)>(); -// declare a threadsafe cancel token to cancel the process loop -var cancel_token = new CancellationTokenSource(); void Main() { AuthToken.Init(".spacetime_csharp_quickstart"); + // TODO: just do `var conn = DbConnection...` when OnConnect signature is fixed. + DbConnection? conn = null; + conn = DbConnection.Builder() .WithUri(HOST) .WithModuleName(DBNAME) //.WithCredentials((null, AuthToken.Token)) - .OnConnect(OnConnect) + // TODO: change this to just `(OnConnect)` when signature is fixed in #131. + .OnConnect((identity, authToken) => OnConnect(conn!, identity, authToken)) .OnConnectError(OnConnectError) .OnDisconnect(OnDisconnect) .Build(); @@ -41,17 +40,19 @@ void Main() conn.RemoteReducers.OnSetName += Reducer_OnSetNameEvent; conn.RemoteReducers.OnSendMessage += Reducer_OnSendMessageEvent; - conn.onSubscriptionApplied += OnSubscriptionApplied; conn.onUnhandledReducerError += onUnhandledReducerError; + // declare a threadsafe cancel token to cancel the process loop + var cancellationTokenSource = new CancellationTokenSource(); + // spawn a thread to call process updates and process commands - var thread = new Thread(ProcessThread); + var thread = new Thread(() => ProcessThread(conn, cancellationTokenSource.Token)); thread.Start(); InputLoop(); // this signals the ProcessThread to stop - cancel_token.Cancel(); + cancellationTokenSource.Cancel(); thread.Join(); } @@ -84,9 +85,9 @@ void User_OnUpdate(EventContext ctx, User oldValue, User newValue) } } -void PrintMessage(Message message) +void PrintMessage(RemoteTables tables, Message message) { - var sender = conn.RemoteTables.User.FindByIdentity(message.Sender); + var sender = tables.User.FindByIdentity(message.Sender); var senderName = "unknown"; if (sender != null) { @@ -100,7 +101,7 @@ void Message_OnInsert(EventContext ctx, Message insertedValue) { if (ctx.Reducer is not Event.SubscribeApplied) { - PrintMessage(insertedValue); + PrintMessage(ctx.Db, insertedValue); } } @@ -128,12 +129,18 @@ void Reducer_OnSendMessageEvent(EventContext ctx, string text) } } -void OnConnect(Identity identity, string authToken) +void OnConnect(DbConnection conn, Identity identity, string authToken) { local_identity = identity; AuthToken.SaveToken(authToken); - conn!.Subscribe(new List { "SELECT * FROM User", "SELECT * FROM Message" }); + conn.SubscriptionBuilder() + .OnApplied(OnSubscriptionApplied) + .Subscribe("SELECT * FROM User"); + + conn.SubscriptionBuilder() + .OnApplied(OnSubscriptionApplied) + .Subscribe("SELECT * FROM Message"); } void OnConnectError(WebSocketError? error, string message) @@ -146,18 +153,18 @@ void OnDisconnect(DbConnection conn, WebSocketCloseStatus? status, WebSocketErro } -void PrintMessagesInOrder() +void PrintMessagesInOrder(RemoteTables tables) { - foreach (Message message in conn.RemoteTables.Message.Iter().OrderBy(item => item.Sent)) + foreach (Message message in tables.Message.Iter().OrderBy(item => item.Sent)) { - PrintMessage(message); + PrintMessage(tables, message); } } -void OnSubscriptionApplied() +void OnSubscriptionApplied(EventContext ctx) { Console.WriteLine("Connected"); - PrintMessagesInOrder(); + PrintMessagesInOrder(ctx.Db); } void onUnhandledReducerError(ReducerEvent reducerEvent) @@ -165,16 +172,16 @@ void onUnhandledReducerError(ReducerEvent reducerEvent) Console.WriteLine($"Unhandled reducer error in {reducerEvent.Reducer}: {reducerEvent.Status}"); } -void ProcessThread() +void ProcessThread(DbConnection conn, CancellationToken ct) { try { // loop until cancellation token - while (!cancel_token.IsCancellationRequested) + while (!ct.IsCancellationRequested) { conn.Update(); - ProcessCommands(); + ProcessCommands(conn.RemoteReducers); Thread.Sleep(100); } @@ -207,7 +214,7 @@ void InputLoop() } } -void ProcessCommands() +void ProcessCommands(RemoteReducers reducers) { // process input queue commands while (input_queue.TryDequeue(out var command)) @@ -215,10 +222,10 @@ void ProcessCommands() switch (command.Command) { case "message": - conn.RemoteReducers.SendMessage(command.Args); + reducers.SendMessage(command.Args); break; case "name": - conn.RemoteReducers.SetName(command.Args); + reducers.SetName(command.Args); break; } } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs index 270481a2511..cf4f4e95ff7 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs @@ -158,5 +158,7 @@ protected override bool Dispatch(IEventContext context, Reducer reducer) { _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } + + public SubscriptionBuilder SubscriptionBuilder() => new(this); } } diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 131cf3f77a8..ff687c0f329 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -35,4 +35,62 @@ public record UnsubscribeApplied : Event; public record SubscribeError(Exception Exception) : Event; public record UnknownTransaction : Event; } -} \ No newline at end of file + + // TODO: Move those classes into EventContext, so that we wouldn't need repetitive generics. + public sealed class SubscriptionBuilder + where EventContext : IEventContext + { + private readonly IDbConnection conn; + private event Action? Applied; + private event Action? Error; + + public SubscriptionBuilder(IDbConnection conn) + { + this.conn = conn; + } + + public SubscriptionBuilder OnApplied(Action callback) + { + Applied += callback; + return this; + } + + public SubscriptionBuilder OnError(Action callback) + { + Error += callback; + return this; + } + + public SubscriptionHandle Subscribe(string querySql) => new(conn, Applied, Error, querySql); + } + + public interface ISubscriptionHandle + { + void OnApplied(IEventContext ctx); + } + + public class SubscriptionHandle : ISubscriptionHandle + where EventContext : IEventContext + { + private readonly Action? onApplied; + + void ISubscriptionHandle.OnApplied(IEventContext ctx) + { + IsActive = true; + onApplied?.Invoke((EventContext)ctx); + } + + internal SubscriptionHandle(IDbConnection conn, Action? onApplied, Action? onError, string querySql) + { + this.onApplied = onApplied; + conn.Subscribe(this, querySql); + } + + public void Unsubscribe() => throw new NotImplementedException(); + + public void UnsuscribeThen(Action onEnd) => throw new NotImplementedException(); + + public bool IsEnded => false; + public bool IsActive { get; private set; } + } +} diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 932cf5b907e..ca18cd847db 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -77,7 +77,12 @@ public DbConnectionBuilder OnDisconnect(Action + public interface IDbConnection + { + void Subscribe(ISubscriptionHandle handle, string query); + } + + public abstract class DbConnectionBase : IDbConnection where DbConnection : DbConnectionBase, new() { public static DbConnectionBuilder Builder() => new(); @@ -108,16 +113,13 @@ struct DbOp /// public event Action? onSendError; + private readonly Dictionary subscriptions = new(); + /// /// Invoked when a subscription is about to start being processed. This is called even before OnBeforeDelete. /// public event Action? onBeforeSubscriptionApplied; - /// - /// Invoked when the local client cache is updated as a result of changes made to the subscription queries. - /// - public event Action? onSubscriptionApplied; - /// /// Invoked when a reducer is returned with an error and has no client-side handler. /// @@ -604,76 +606,82 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) switch (message) { case ServerMessage.InitialSubscription(var initialSubscription): - onBeforeSubscriptionApplied?.Invoke(); - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.InitialSubscription)}"); - stats.SubscriptionRequestTracker.FinishTrackingRequest(initialSubscription.RequestId); - OnMessageProcessCompleteUpdate(ToEventContext(new Event.SubscribeApplied()), dbOps); - try - { - onSubscriptionApplied?.Invoke(); - } - catch (Exception e) { - Log.Exception(e); + onBeforeSubscriptionApplied?.Invoke(); + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.InitialSubscription)}"); + stats.SubscriptionRequestTracker.FinishTrackingRequest(initialSubscription.RequestId); + var eventContext = ToEventContext(new Event.SubscribeApplied()); + OnMessageProcessCompleteUpdate(eventContext, dbOps); + if (subscriptions.TryGetValue(initialSubscription.RequestId, out var subscription)) + { + try + { + subscription.OnApplied(eventContext); + } + catch (Exception e) + { + Log.Exception(e); + } + } + break; } - break; - case ServerMessage.TransactionUpdate(var transactionUpdate): - var reducer = transactionUpdate.ReducerCall.ReducerName; - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdate)},reducer={reducer}"); - var hostDuration = TimeSpan.FromMilliseconds(transactionUpdate.HostExecutionDurationMicros / 1000.0d); - stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); - var callerIdentity = transactionUpdate.CallerIdentity; - if (callerIdentity == clientIdentity) { - // This was a request that we initiated - var requestId = transactionUpdate.ReducerCall.RequestId; - if (!stats.ReducerRequestTracker.FinishTrackingRequest(requestId)) + var reducer = transactionUpdate.ReducerCall.ReducerName; + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdate)},reducer={reducer}"); + var hostDuration = TimeSpan.FromMilliseconds(transactionUpdate.HostExecutionDurationMicros / 1000.0d); + stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); + var callerIdentity = transactionUpdate.CallerIdentity; + if (callerIdentity == clientIdentity) { - Log.Warn($"Failed to finish tracking reducer request: {requestId}"); + // This was a request that we initiated + var requestId = transactionUpdate.ReducerCall.RequestId; + if (!stats.ReducerRequestTracker.FinishTrackingRequest(requestId)) + { + Log.Warn($"Failed to finish tracking reducer request: {requestId}"); + } } - } - if (processed.reducerEvent is not { } reducerEvent) - { - // If we are here, an error about unknown reducer should have already been logged, so nothing to do. - break; - } - - var eventContext = ToEventContext(new Event.Reducer(reducerEvent)); - OnMessageProcessCompleteUpdate(eventContext, dbOps); - try - { - onEvent?.Invoke(message); - } - catch (Exception e) - { - Log.Exception(e); - } + if (processed.reducerEvent is not { } reducerEvent) + { + // If we are here, an error about unknown reducer should have already been logged, so nothing to do. + break; + } - var reducerFound = false; - try - { - reducerFound = Dispatch(eventContext, reducerEvent.Reducer); - } - catch (Exception e) - { - Log.Exception(e); - } + var eventContext = ToEventContext(new Event.Reducer(reducerEvent)); + OnMessageProcessCompleteUpdate(eventContext, dbOps); + try + { + onEvent?.Invoke(message); + } + catch (Exception e) + { + Log.Exception(e); + } - if (!reducerFound && transactionUpdate.Status is UpdateStatus.Failed(var failed)) - { + var reducerFound = false; try { - onUnhandledReducerError?.Invoke(reducerEvent); + reducerFound = Dispatch(eventContext, reducerEvent.Reducer); } catch (Exception e) { Log.Exception(e); } - } - break; + if (!reducerFound && transactionUpdate.Status is UpdateStatus.Failed(var failed)) + { + try + { + onUnhandledReducerError?.Invoke(reducerEvent); + } + catch (Exception e) + { + Log.Exception(e); + } + } + break; + } case ServerMessage.IdentityToken(var identityToken): try { @@ -725,7 +733,7 @@ public void InternalCallReducer(T args) )); } - public void Subscribe(List queries) + void IDbConnection.Subscribe(ISubscriptionHandle handle, string query) { if (!webSocket.IsConnected) { @@ -733,12 +741,15 @@ public void Subscribe(List queries) return; } - var request = new Subscribe - { - RequestId = stats.SubscriptionRequestTracker.StartTrackingRequest(), - }; - request.QueryStrings.AddRange(queries); - webSocket.Send(new ClientMessage.Subscribe(request)); + var id = stats.SubscriptionRequestTracker.StartTrackingRequest(); + subscriptions[id] = handle; + webSocket.Send(new ClientMessage.Subscribe( + new Subscribe + { + RequestId = id, + QueryStrings = { query } + } + )); } /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("WHERE sender = \"bob\""); diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 72486fa632f..e99e601c234 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -297,7 +297,6 @@ public async Task VerifyAllTablesParsed() }); client.onConnect += (identity, _token) => events.Add("OnIdentityReceived", identity); - client.onSubscriptionApplied += () => events.Add("OnSubscriptionApplied"); client.onUnhandledReducerError += (exception) => events.Add("OnUnhandledReducerError", exception); From 87a13eb74f139f2b56da0fe060bcb57bcf60dc01 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 1 Oct 2024 17:37:42 +0100 Subject: [PATCH 114/223] Merge table cache into table handle (#139) ## Description of Changes Merges cache into the table handle as suggested on the original PR + hides most table methods that shouldn't be part of the stable API. Few remaining methods will need a codegen change to be available only to subclasses, so for now that's out of scope. Same for merging ClientCache into RemoteTables - we shouldn't need a separate collection, and instead could autogenerate a switch expression over table name. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/ClientCache.cs | 66 +++------------------- sdks/csharp/src/SpacetimeDBClient.cs | 44 +++++++-------- sdks/csharp/src/Table.cs | 82 ++++++++++++++++++++-------- 3 files changed, 87 insertions(+), 105 deletions(-) diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 9992f0cbf7f..824ca34b1e2 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -6,74 +6,22 @@ namespace SpacetimeDB { + // TODO: merge this into `RemoteTables`. + // It should just provide auto-generated `GetTable` and `GetTables` methods. public class ClientCache { - public interface ITableCache : IEnumerable> - { - Type ClientTableType { get; } - bool InsertEntry(byte[] rowBytes, IDatabaseRow value); - bool DeleteEntry(byte[] rowBytes); - IDatabaseRow DecodeValue(byte[] bytes); - IRemoteTableHandle Handle { get; } - } - - public class TableCache : ITableCache - where Row : IDatabaseRow, new() - { - public TableCache(IRemoteTableHandle handle) => Handle = handle; - - public IRemoteTableHandle Handle { get; init; } - - public Type ClientTableType => typeof(Row); - - public readonly Dictionary Entries = new(ByteArrayComparer.Instance); - - /// - /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. - /// - /// The BSATN encoded bytes of the row to retrieve. - /// The parsed row encoded by the rowBytes. - /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. - public bool InsertEntry(byte[] rowBytes, IDatabaseRow value) => Entries.TryAdd(rowBytes, (Row)value); - - /// - /// Deletes a value from the table. - /// - /// The BSATN encoded bytes of the row to remove. - /// True if and only if the value was previously resident and has been deleted. - public bool DeleteEntry(byte[] rowBytes) - { - if (Entries.Remove(rowBytes)) - { - return true; - } - - Log.Warn("Deleting value that we don't have (no cached value available)"); - return false; - } - - // The function to use for decoding a type value. - public IDatabaseRow DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); - - public IEnumerator> GetEnumerator() => Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - private readonly Dictionary tables = new(); + private readonly Dictionary tables = new(); - public void AddTable(string name, IRemoteTableHandle handle) + public void AddTable(string name, IRemoteTableHandle table) where Row : IDatabaseRow, new() { - var cache = new TableCache(handle); - handle.SetCache(cache); - if (!tables.TryAdd(name, cache)) + if (!tables.TryAdd(name, table)) { Log.Error($"Table with name already exists: {name}"); } } - public ITableCache? GetTable(string name) + public IRemoteTableHandle? GetTable(string name) { if (tables.TryGetValue(name, out var table)) { @@ -84,6 +32,6 @@ public void AddTable(string name, IRemoteTableHandle handle) return null; } - public IEnumerable GetTables() => tables.Values; + public IEnumerable GetTables() => tables.Values; } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index ca18cd847db..fcdcdce8766 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -87,10 +87,10 @@ public abstract class DbConnectionBase : IDbConnection { public static DbConnectionBuilder Builder() => new(); - struct DbValue + readonly struct DbValue { - public IDatabaseRow value; - public byte[] bytes; + public readonly IDatabaseRow value; + public readonly byte[] bytes; public DbValue(IDatabaseRow value, byte[] bytes) { @@ -101,7 +101,7 @@ public DbValue(IDatabaseRow value, byte[] bytes) struct DbOp { - public ClientCache.ITableCache table; + public IRemoteTableHandle table; public DbValue? delete; public DbValue? insert; } @@ -193,12 +193,14 @@ struct PreProcessedMessage private readonly CancellationTokenSource _preProcessCancellationTokenSource = new(); private CancellationToken _preProcessCancellationToken => _preProcessCancellationTokenSource.Token; - static DbValue Decode(ClientCache.ITableCache table, EncodedValue value) => value switch + static DbValue Decode(IRemoteTableHandle table, EncodedValue value, out object? primaryKey) { - EncodedValue.Binary(var bin) => new DbValue(table.DecodeValue(bin), bin), - EncodedValue.Text(var text) => throw new InvalidOperationException("JavaScript messages aren't supported."), - _ => throw new InvalidOperationException(), - }; + // We expect only binary messages here; let type cast exception take care of any others. + var bin = ((EncodedValue.Binary)value).Binary_; + var obj = table.DecodeValue(bin); + primaryKey = table.GetPrimaryKey(obj); + return new(obj, bin); + } private static readonly Status Committed = new Status.Committed(default); private static readonly Status OutOfEnergy = new Status.OutOfEnergy(default); @@ -337,8 +339,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) foreach (var row in update.Inserts) { - var op = new DbOp { table = table, insert = Decode(table, row) }; - var pk = table.Handle.GetPrimaryKey(op.insert.Value.value); + var op = new DbOp { table = table, insert = Decode(table, row, out var pk) }; if (pk != null) { // Compound key that we use for lookup. @@ -373,8 +374,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) foreach (var row in update.Deletes) { - var op = new DbOp { table = table, delete = Decode(table, row) }; - var pk = table.Handle.GetPrimaryKey(op.delete.Value.value); + var op = new DbOp { table = table, delete = Decode(table, row, out var pk) }; if (pk != null) { // Compound key that we use for lookup. @@ -454,7 +454,7 @@ ProcessedMessage CalculateStateDiff(PreProcessedMessage preProcessedMessage) continue; } - foreach (var (rowBytes, oldValue) in table.Where(kv => !hashSet.Contains(kv.Key))) + foreach (var (rowBytes, oldValue) in table.IterEntries().Where(kv => !hashSet.Contains(kv.Key))) { processed.dbOps.Add(new DbOp { @@ -523,7 +523,7 @@ private void OnMessageProcessCompleteUpdate(IEventContext eventContext, List> IterEntries(); + internal bool InsertEntry(byte[] rowBytes, IDatabaseRow value); + internal bool DeleteEntry(byte[] rowBytes); + internal IDatabaseRow DecodeValue(byte[] bytes); + + internal void InvokeInsert(IEventContext context, IDatabaseRow row); + internal void InvokeDelete(IEventContext context, IDatabaseRow row); + internal void InvokeBeforeDelete(IEventContext context, IDatabaseRow row); + internal void InvokeUpdate(IEventContext context, IDatabaseRow oldRow, IDatabaseRow newRow); } public abstract class RemoteTableHandle : IRemoteTableHandle where EventContext : class, IEventContext where Row : IDatabaseRow, new() { - public void SetCache(ClientCache.ITableCache cache) => Cache = (ClientCache.TableCache)cache; + // These methods need to be overridden by autogen. + public virtual object? GetPrimaryKey(IDatabaseRow row) => null; + public virtual void InternalInvokeValueInserted(IDatabaseRow row) { } + public virtual void InternalInvokeValueDeleted(IDatabaseRow row) { } + + // These are provided by RemoteTableHandle. + Type IRemoteTableHandle.ClientTableType => typeof(Row); + + private readonly Dictionary Entries = new(Internal.ByteArrayComparer.Instance); + + IEnumerable> IRemoteTableHandle.IterEntries() => + Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)); + + /// + /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. + /// + /// The BSATN encoded bytes of the row to retrieve. + /// The parsed row encoded by the rowBytes. + /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. + bool IRemoteTableHandle.InsertEntry(byte[] rowBytes, IDatabaseRow value) => Entries.TryAdd(rowBytes, (Row)value); - internal ClientCache.TableCache? Cache; + /// + /// Deletes a value from the table. + /// + /// The BSATN encoded bytes of the row to remove. + /// True if and only if the value was previously resident and has been deleted. + bool IRemoteTableHandle.DeleteEntry(byte[] rowBytes) + { + if (Entries.Remove(rowBytes)) + { + return true; + } + + Log.Warn("Deleting value that we don't have (no cached value available)"); + return false; + } + + // The function to use for decoding a type value. + IDatabaseRow IRemoteTableHandle.DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); public event Action? OnInsert; public event Action? OnDelete; public event Action? OnBeforeDelete; public event Action? OnUpdate; - public virtual object? GetPrimaryKey(IDatabaseRow row) => null; - - public virtual void InternalInvokeValueInserted(IDatabaseRow row) { } - - public virtual void InternalInvokeValueDeleted(IDatabaseRow row) { } - - public int Count => Cache!.Entries.Count; + public int Count => Entries.Count; - public IEnumerable Iter() => Cache!.Entries.Values; + public IEnumerable Iter() => Entries.Values; - public IEnumerable Query(Func filter) => Iter().Where(filter); + protected IEnumerable Query(Func filter) => Iter().Where(filter); - public void InvokeInsert(IEventContext context, IDatabaseRow row) => + void IRemoteTableHandle.InvokeInsert(IEventContext context, IDatabaseRow row) => OnInsert?.Invoke((EventContext)context, (Row)row); - public void InvokeDelete(IEventContext context, IDatabaseRow row) => + void IRemoteTableHandle.InvokeDelete(IEventContext context, IDatabaseRow row) => OnDelete?.Invoke((EventContext)context, (Row)row); - public void InvokeBeforeDelete(IEventContext context, IDatabaseRow row) => + void IRemoteTableHandle.InvokeBeforeDelete(IEventContext context, IDatabaseRow row) => OnBeforeDelete?.Invoke((EventContext)context, (Row)row); - public void InvokeUpdate(IEventContext context, IDatabaseRow oldRow, IDatabaseRow newRow) => + void IRemoteTableHandle.InvokeUpdate(IEventContext context, IDatabaseRow oldRow, IDatabaseRow newRow) => OnUpdate?.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); } -} \ No newline at end of file +} From 113e8dd972b1801b8d733ac105eb38f69003f8d0 Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Tue, 1 Oct 2024 13:02:54 -0400 Subject: [PATCH 115/223] Add DbConnection argument to OnConnect (#138) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/examples~/quickstart/client/Program.cs | 3 +-- sdks/csharp/src/SpacetimeDBClient.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index cd378c594d2..0f62f3d4563 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -26,8 +26,7 @@ void Main() .WithUri(HOST) .WithModuleName(DBNAME) //.WithCredentials((null, AuthToken.Token)) - // TODO: change this to just `(OnConnect)` when signature is fixed in #131. - .OnConnect((identity, authToken) => OnConnect(conn!, identity, authToken)) + .OnConnect(OnConnect) .OnConnectError(OnConnectError) .OnDisconnect(OnDisconnect) .Build(); diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index fcdcdce8766..b7c405f811e 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -58,9 +58,9 @@ public DbConnectionBuilder WithCredentials(in (Identity i return this; } - public DbConnectionBuilder OnConnect(Action cb) + public DbConnectionBuilder OnConnect(Action cb) { - conn.onConnect += cb; + conn.onConnect += (identity, token) => cb.Invoke(conn, identity, token); return this; } From cfd654f94ce54e06659af31f5f4e46a74d16a48f Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 1 Oct 2024 20:00:32 +0100 Subject: [PATCH 116/223] Hide more APIs (#140) ## Description of Changes Removing unstable APIs that are not used by BitCraft; marking others with [Obsolete] and renaming few others to match the proposal. One exception is InternalCallReducer - it would need some further changes to codegen; marking it as Obsolete right now would cause all generated clients to show noisy warnings. ## API - [x] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- .../examples~/quickstart/client/Program.cs | 6 +- sdks/csharp/src/ClientCache.cs | 4 +- sdks/csharp/src/ConsoleLogger.cs | 2 +- sdks/csharp/src/SpacetimeDBClient.cs | 50 +++----- sdks/csharp/src/UnityDebugLogger.cs | 2 +- sdks/csharp/src/WebSocket.cs | 33 +++--- ...otTests.VerifyAllTablesParsed.verified.txt | 108 +----------------- sdks/csharp/tests~/SnapshotTests.cs | 23 ++-- sdks/csharp/tests~/tests.csproj | 2 +- 9 files changed, 52 insertions(+), 178 deletions(-) diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index 0f62f3d4563..29ad6c95c97 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -39,7 +39,9 @@ void Main() conn.RemoteReducers.OnSetName += Reducer_OnSetNameEvent; conn.RemoteReducers.OnSendMessage += Reducer_OnSendMessageEvent; +#pragma warning disable CS0612 // Using obsolete API conn.onUnhandledReducerError += onUnhandledReducerError; +#pragma warning restore CS0612 // Using obsolete API // declare a threadsafe cancel token to cancel the process loop var cancellationTokenSource = new CancellationTokenSource(); @@ -178,7 +180,7 @@ void ProcessThread(DbConnection conn, CancellationToken ct) // loop until cancellation token while (!ct.IsCancellationRequested) { - conn.Update(); + conn.FrameTick(); ProcessCommands(conn.RemoteReducers); @@ -187,7 +189,7 @@ void ProcessThread(DbConnection conn, CancellationToken ct) } finally { - conn.Close(); + conn.Disconnect(); } } diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 824ca34b1e2..0ec8ad911bc 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -21,7 +21,7 @@ public void AddTable(string name, IRemoteTableHandle table) } } - public IRemoteTableHandle? GetTable(string name) + internal IRemoteTableHandle? GetTable(string name) { if (tables.TryGetValue(name, out var table)) { @@ -32,6 +32,6 @@ public void AddTable(string name, IRemoteTableHandle table) return null; } - public IEnumerable GetTables() => tables.Values; + internal IEnumerable GetTables() => tables.Values; } } diff --git a/sdks/csharp/src/ConsoleLogger.cs b/sdks/csharp/src/ConsoleLogger.cs index 1711899cf46..2fda0ab5b2f 100644 --- a/sdks/csharp/src/ConsoleLogger.cs +++ b/sdks/csharp/src/ConsoleLogger.cs @@ -2,7 +2,7 @@ namespace SpacetimeDB { - public class ConsoleLogger : ISpacetimeDBLogger + internal class ConsoleLogger : ISpacetimeDBLogger { [Flags] public enum LogLevel diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index b7c405f811e..88c85cccee4 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -111,27 +111,19 @@ struct DbOp /// /// Called when an exception occurs when sending a message. /// + [Obsolete] public event Action? onSendError; private readonly Dictionary subscriptions = new(); - /// - /// Invoked when a subscription is about to start being processed. This is called even before OnBeforeDelete. - /// - public event Action? onBeforeSubscriptionApplied; - /// /// Invoked when a reducer is returned with an error and has no client-side handler. /// + [Obsolete] public event Action>? onUnhandledReducerError; - /// - /// Invoked when an event message is received or at the end of a transaction update. - /// - public event Action? onEvent; - - public readonly Address clientAddress = Address.Random(); - public Identity? clientIdentity { get; private set; } + public readonly Address Address = Address.Random(); + public Identity? Identity { get; private set; } internal WebSocket webSocket; private bool connectionClosed; @@ -148,7 +140,7 @@ struct DbOp protected DbConnectionBase() { - var options = new ConnectOptions + var options = new WebSocket.ConnectOptions { //v1.bin.spacetimedb //v1.text.spacetimedb @@ -470,7 +462,7 @@ ProcessedMessage CalculateStateDiff(PreProcessedMessage preProcessedMessage) return processed; } - public void Close() + public void Disconnect() { isClosing = true; connectionClosed = true; @@ -483,7 +475,7 @@ public void Close() /// /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - public void Connect(string? token, string uri, string addressOrName) + internal void Connect(string? token, string uri, string addressOrName) { isClosing = false; @@ -499,7 +491,7 @@ public void Connect(string? token, string uri, string addressOrName) { try { - await webSocket.Connect(token, uri, addressOrName, clientAddress); + await webSocket.Connect(token, uri, addressOrName, Address); } catch (Exception e) { @@ -605,7 +597,6 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) { case ServerMessage.InitialSubscription(var initialSubscription): { - onBeforeSubscriptionApplied?.Invoke(); stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.InitialSubscription)}"); stats.SubscriptionRequestTracker.FinishTrackingRequest(initialSubscription.RequestId); var eventContext = ToEventContext(new Event.SubscribeApplied()); @@ -630,7 +621,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) var hostDuration = TimeSpan.FromMilliseconds(transactionUpdate.HostExecutionDurationMicros / 1000.0d); stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); var callerIdentity = transactionUpdate.CallerIdentity; - if (callerIdentity == clientIdentity) + if (callerIdentity == Identity) { // This was a request that we initiated var requestId = transactionUpdate.ReducerCall.RequestId; @@ -648,14 +639,6 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) var eventContext = ToEventContext(new Event.Reducer(reducerEvent)); OnMessageProcessCompleteUpdate(eventContext, dbOps); - try - { - onEvent?.Invoke(message); - } - catch (Exception e) - { - Log.Exception(e); - } var reducerFound = false; try @@ -683,7 +666,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) case ServerMessage.IdentityToken(var identityToken): try { - clientIdentity = identityToken.Identity; + Identity = identityToken.Identity; onConnect?.Invoke(identityToken.Identity, identityToken.Token); } catch (Exception e) @@ -693,14 +676,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) break; case ServerMessage.OneOffQueryResponse: - try - { - onEvent?.Invoke(message); - } - catch (Exception e) - { - Log.Exception(e); - } + /* OneOffQuery is async and handles its own responses */ break; default: @@ -807,9 +783,9 @@ T[] LogAndThrow(string error) return resultTable.Rows.Select(BSATNHelpers.Decode).ToArray(); } - public bool IsConnected() => webSocket.IsConnected; + public bool IsActive => webSocket.IsConnected; - public void Update() + public void FrameTick() { webSocket.Update(); while (_preProcessedNetworkMessages.TryTake(out var preProcessedMessage)) diff --git a/sdks/csharp/src/UnityDebugLogger.cs b/sdks/csharp/src/UnityDebugLogger.cs index 114079f0688..218cde182e0 100644 --- a/sdks/csharp/src/UnityDebugLogger.cs +++ b/sdks/csharp/src/UnityDebugLogger.cs @@ -8,7 +8,7 @@ namespace SpacetimeDB { - public class UnityDebugLogger : ISpacetimeDBLogger + internal class UnityDebugLogger : ISpacetimeDBLogger { public void Debug(string message) { diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 73d23e9a552..cd22c26feac 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -11,23 +11,22 @@ namespace SpacetimeDB { - public delegate void WebSocketOpenEventHandler(); - - public delegate void WebSocketMessageEventHandler(byte[] message, DateTime timestamp); + internal class WebSocket + { + public delegate void OpenEventHandler(); - public delegate void WebSocketCloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); + public delegate void MessageEventHandler(byte[] message, DateTime timestamp); - public delegate void WebSocketConnectErrorEventHandler(WebSocketError? error, string message); - public delegate void WebSocketSendErrorEventHandler(Exception e); + public delegate void CloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); - public struct ConnectOptions - { - public string Protocol; - } + public delegate void ConnectErrorEventHandler(WebSocketError? error, string message); + public delegate void SendErrorEventHandler(Exception e); + public struct ConnectOptions + { + public string Protocol; + } - public class WebSocket - { // WebSocket buffer for incoming messages private static readonly int MAXMessageSize = 0x4000000; // 64MB @@ -43,11 +42,11 @@ public WebSocket(ConnectOptions options) _options = options; } - public event WebSocketOpenEventHandler? OnConnect; - public event WebSocketConnectErrorEventHandler? OnConnectError; - public event WebSocketSendErrorEventHandler? OnSendError; - public event WebSocketMessageEventHandler? OnMessage; - public event WebSocketCloseEventHandler? OnClose; + public event OpenEventHandler? OnConnect; + public event ConnectErrorEventHandler? OnConnectError; + public event SendErrorEventHandler? OnSendError; + public event MessageEventHandler? OnMessage; + public event CloseEventHandler? OnClose; public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } diff --git a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt index fd948740840..513aa66c49d 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -1,6 +1,10 @@ { Events: { - OnIdentityReceived: Identity_1, + Log: SpacetimeDBClient: Connecting to wss://spacetimedb.com example, + OnConnect: { + identity: Identity_1, + token: eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiI4ZjkwY2M5NGE5OTY4ZGY2ZDI5N2JhYTY2NTAzYTg5M2IxYzM0YjBiMDAyNjhhNTE0ODk4ZGQ5NTRiMGRhMjBiIiwiaWF0IjoxNzE4NDg3NjY4LCJleHAiOm51bGx9.PSn481bLRqtFwIh46nOXDY14X3GKbz8t4K4GmBmz50loU6xzeL7zDdCh1V2cmiQsoGq8Erxg0r_6b6Y5SqKoBA + }, OnInsertUser: { eventContext: { Reducers: {Scrubbed}, @@ -33,18 +37,6 @@ online: true } }, - OnEvent: { - status: {Scrubbed}, - timestamp: 1718487763059031, - caller_identity: Identity_2, - caller_address: Guid_1, - reducer_call: { - reducer_name: __identity_connected__, - args: - }, - energy_quanta_used: 1957615, - host_execution_duration_micros: 66 - }, OnUpdateUser: { eventContext: { Reducers: {Scrubbed}, @@ -74,19 +66,6 @@ online: true } }, - OnEvent: { - status: {Scrubbed}, - timestamp: 1718487768057579, - caller_identity: Identity_1, - caller_address: Guid_2, - reducer_call: { - reducer_name: set_name, - args: AQAAAEE=, - request_id: 1 - }, - energy_quanta_used: 4345615, - host_execution_duration_micros: 70 - }, OnSetName: { Reducers: {Scrubbed}, Reducer: { @@ -130,19 +109,6 @@ text: Hello, A! } }, - OnEvent: { - status: {Scrubbed}, - timestamp: 1718487775346381, - caller_identity: Identity_2, - caller_address: Guid_1, - reducer_call: { - reducer_name: send_message, - args: CQAAAEhlbGxvLCBBIQ==, - request_id: 1 - }, - energy_quanta_used: 2779615, - host_execution_duration_micros: 57 - }, OnSendMessage: { Reducers: {Scrubbed}, Reducer: { @@ -190,19 +156,6 @@ online: true } }, - OnEvent: { - status: {Scrubbed}, - timestamp: 1718487777307855, - caller_identity: Identity_2, - caller_address: Guid_1, - reducer_call: { - reducer_name: set_name, - args: AQAAAEI=, - request_id: 2 - }, - energy_quanta_used: 4268615, - host_execution_duration_micros: 98 - }, OnSetName: { Reducers: {Scrubbed}, Reducer: { @@ -246,19 +199,6 @@ text: Hello, B! } }, - OnEvent: { - status: {Scrubbed}, - timestamp: 1718487783175083, - caller_identity: Identity_1, - caller_address: Guid_2, - reducer_call: { - reducer_name: send_message, - args: CQAAAEhlbGxvLCBCIQ==, - request_id: 2 - }, - energy_quanta_used: 2677615, - host_execution_duration_micros: 40 - }, OnSendMessage: { Reducers: {Scrubbed}, Reducer: { @@ -302,19 +242,6 @@ text: Goodbye! } }, - OnEvent: { - status: {Scrubbed}, - timestamp: 1718487787645364, - caller_identity: Identity_2, - caller_address: Guid_1, - reducer_call: { - reducer_name: send_message, - args: CAAAAEdvb2RieWUh, - request_id: 3 - }, - energy_quanta_used: 2636615, - host_execution_duration_micros: 28 - }, OnSendMessage: { Reducers: {Scrubbed}, Reducer: { @@ -359,18 +286,6 @@ online: false } }, - OnEvent: { - status: {Scrubbed}, - timestamp: 1718487791901504, - caller_identity: Identity_2, - caller_address: Guid_1, - reducer_call: { - reducer_name: __identity_disconnected__, - args: - }, - energy_quanta_used: 3595615, - host_execution_duration_micros: 75 - }, OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, @@ -396,19 +311,6 @@ text: Goodbye! } }, - OnEvent: { - status: {Scrubbed}, - timestamp: 1718487794937841, - caller_identity: Identity_1, - caller_address: Guid_2, - reducer_call: { - reducer_name: send_message, - args: CAAAAEdvb2RieWUh, - request_id: 3 - }, - energy_quanta_used: 2636615, - host_execution_duration_micros: 34 - }, OnSendMessage: { Reducers: {Scrubbed}, Reducer: { diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index e99e601c234..dd08dfe6a86 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -258,7 +258,12 @@ public async Task VerifyAllTablesParsed() Log.Current = new TestLogger(events); - var client = new DbConnection(); + var client = + DbConnection.Builder() + .WithUri("wss://spacetimedb.com") + .WithModuleName("example") + .OnConnect((conn, identity, token) => events.Add("OnConnect", new { identity, token })) + .Build(); var sampleDumpParsed = SampleDump(); @@ -286,20 +291,10 @@ public async Task VerifyAllTablesParsed() } ); - client.onBeforeSubscriptionApplied += () => events.Add("OnBeforeSubscriptionApplied"); - client.onEvent += (ev) => events.Add("OnEvent", ev switch - { - ServerMessage.IdentityToken(var o) => o, - ServerMessage.InitialSubscription(var o) => o, - ServerMessage.TransactionUpdate(var o) => o, - ServerMessage.OneOffQueryResponse(var o) => o, - _ => throw new InvalidOperationException() - }); - client.onConnect += (identity, _token) => - events.Add("OnIdentityReceived", identity); +#pragma warning disable CS0612 // Using obsolete API client.onUnhandledReducerError += (exception) => events.Add("OnUnhandledReducerError", exception); - +#pragma warning restore CS0612 // Using obsolete API client.RemoteReducers.OnSendMessage += (eventContext, _text) => events.Add("OnSendMessage", eventContext); client.RemoteReducers.OnSetName += (eventContext, _name) => events.Add("OnSetName", eventContext); @@ -332,7 +327,7 @@ public async Task VerifyAllTablesParsed() // Otherwise we'll get inconsistent output order between test reruns. while (!client.HasPreProcessedMessage) { } // Once the message is in the preprocessed queue, we can invoke Update() to handle events on the main thread. - client.Update(); + client.FrameTick(); } // Verify dumped events and the final client state. diff --git a/sdks/csharp/tests~/tests.csproj b/sdks/csharp/tests~/tests.csproj index 23735fb4623..804fa736c4d 100644 --- a/sdks/csharp/tests~/tests.csproj +++ b/sdks/csharp/tests~/tests.csproj @@ -23,7 +23,7 @@ - + From b62a4643845645352436309131dc54c99c5e83a3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 2 Oct 2024 17:18:24 +0200 Subject: [PATCH 117/223] Implement websocket changes atop C# sdk changes (#136) ## Requires SpacetimeDB PRs This is the C# side of https://github.com/clockworklabs/SpacetimeDB/pull/1761. --- sdks/csharp/src/BSATNHelpers.cs | 7 - .../src/SpacetimeDB/ClientApi/BsatnRowList.cs | 40 +++ .../src/SpacetimeDB/ClientApi/CallReducer.cs | 21 +- .../ClientApi/CompressableQueryUpdate.cs | 17 ++ .../SpacetimeDB/ClientApi/DatabaseUpdate.cs | 14 +- .../ClientApi/EncodedValue.cs.meta | 11 - .../src/SpacetimeDB/ClientApi/EnergyQuanta.cs | 11 + .../SpacetimeDB/ClientApi/IdentityToken.cs | 24 +- .../ClientApi/InitialSubscription.cs | 18 +- .../src/SpacetimeDB/ClientApi/OneOffQuery.cs | 19 +- .../ClientApi/OneOffQueryResponse.cs | 23 +- .../src/SpacetimeDB/ClientApi/OneOffTable.cs | 19 +- .../src/SpacetimeDB/ClientApi/QueryUpdate.cs | 40 +++ .../SpacetimeDB/ClientApi/ReducerCallInfo.cs | 23 +- .../{EncodedValue.cs => RowSizeHint.cs} | 6 +- .../src/SpacetimeDB/ClientApi/Subscribe.cs | 16 +- .../src/SpacetimeDB/ClientApi/TableUpdate.cs | 29 +- .../src/SpacetimeDB/ClientApi/Timestamp.cs | 11 + .../ClientApi/TransactionUpdate.cs | 41 ++- sdks/csharp/src/SpacetimeDBClient.cs | 277 ++++++++++++------ ...otTests.VerifyAllTablesParsed.verified.txt | 2 +- sdks/csharp/tests~/SnapshotTests.cs | 64 ++-- 22 files changed, 567 insertions(+), 166 deletions(-) create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{EncodedValue.cs => RowSizeHint.cs} (66%) diff --git a/sdks/csharp/src/BSATNHelpers.cs b/sdks/csharp/src/BSATNHelpers.cs index 31f156284ec..46c4cb6443e 100644 --- a/sdks/csharp/src/BSATNHelpers.cs +++ b/sdks/csharp/src/BSATNHelpers.cs @@ -25,12 +25,5 @@ public static T Decode(string json) { throw new InvalidOperationException("JSON isn't supported at the moment"); } - - public static T Decode(EncodedValue value) where T : IStructuralReadWrite, new() => value switch - { - EncodedValue.Binary(var bin) => Decode(bin), - EncodedValue.Text(var text) => Decode(text), - _ => throw new InvalidOperationException() - }; } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs new file mode 100644 index 00000000000..5df43d6bc96 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs @@ -0,0 +1,40 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class BsatnRowList + { + [DataMember(Name = "size_hint")] + public SpacetimeDB.ClientApi.RowSizeHint SizeHint; + [DataMember(Name = "rows_data")] + public byte[] RowsData; + + public BsatnRowList( + SpacetimeDB.ClientApi.RowSizeHint SizeHint, + byte[] RowsData + ) + { + this.SizeHint = SizeHint; + this.RowsData = RowsData; + } + + public BsatnRowList() + { + this.SizeHint = null!; + this.RowsData = Array.Empty(); + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs index d3f56f381ca..7c3ce90eaec 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs @@ -17,11 +17,28 @@ namespace SpacetimeDB.ClientApi public partial class CallReducer { [DataMember(Name = "reducer")] - public string Reducer = ""; + public string Reducer; [DataMember(Name = "args")] - public SpacetimeDB.ClientApi.EncodedValue Args = null!; + public byte[] Args; [DataMember(Name = "request_id")] public uint RequestId; + public CallReducer( + string Reducer, + byte[] Args, + uint RequestId + ) + { + this.Reducer = Reducer; + this.Args = Args; + this.RequestId = RequestId; + } + + public CallReducer() + { + this.Reducer = ""; + this.Args = Array.Empty(); + } + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs new file mode 100644 index 00000000000..af397a580bd --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs @@ -0,0 +1,17 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record CompressableQueryUpdate : SpacetimeDB.TaggedEnum<( + SpacetimeDB.ClientApi.QueryUpdate Uncompressed, + byte[] Brotli + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs index 245117ad702..3294c6b77df 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs @@ -17,7 +17,19 @@ namespace SpacetimeDB.ClientApi public partial class DatabaseUpdate { [DataMember(Name = "tables")] - public System.Collections.Generic.List Tables = new(); + public System.Collections.Generic.List Tables; + + public DatabaseUpdate( + System.Collections.Generic.List Tables + ) + { + this.Tables = Tables; + } + + public DatabaseUpdate() + { + this.Tables = new(); + } } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs.meta deleted file mode 100644 index c89e37b1e22..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 16581799d308744cbba931760b17b64c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs index ba142cb3385..476712e9661 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs @@ -19,5 +19,16 @@ public partial class EnergyQuanta [DataMember(Name = "quanta")] public U128 Quanta; + public EnergyQuanta( + U128 Quanta + ) + { + this.Quanta = Quanta; + } + + public EnergyQuanta() + { + } + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs index 344cbbba87e..4a53ad2fd8a 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs @@ -17,11 +17,29 @@ namespace SpacetimeDB.ClientApi public partial class IdentityToken { [DataMember(Name = "identity")] - public SpacetimeDB.Identity Identity = new(); + public SpacetimeDB.Identity Identity; [DataMember(Name = "token")] - public string Token = ""; + public string Token; [DataMember(Name = "address")] - public SpacetimeDB.Address Address = new(); + public SpacetimeDB.Address Address; + + public IdentityToken( + SpacetimeDB.Identity Identity, + string Token, + SpacetimeDB.Address Address + ) + { + this.Identity = Identity; + this.Token = Token; + this.Address = Address; + } + + public IdentityToken() + { + this.Identity = new(); + this.Token = ""; + this.Address = new(); + } } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs index 06ae7ba854e..cdbc73de2a7 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs @@ -17,11 +17,27 @@ namespace SpacetimeDB.ClientApi public partial class InitialSubscription { [DataMember(Name = "database_update")] - public SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate = new(); + public SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate; [DataMember(Name = "request_id")] public uint RequestId; [DataMember(Name = "total_host_execution_duration_micros")] public ulong TotalHostExecutionDurationMicros; + public InitialSubscription( + SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate, + uint RequestId, + ulong TotalHostExecutionDurationMicros + ) + { + this.DatabaseUpdate = DatabaseUpdate; + this.RequestId = RequestId; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + } + + public InitialSubscription() + { + this.DatabaseUpdate = new(); + } + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs index c103c829f52..5ee2c66dc8e 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs @@ -17,9 +17,24 @@ namespace SpacetimeDB.ClientApi public partial class OneOffQuery { [DataMember(Name = "message_id")] - public byte[] MessageId = Array.Empty(); + public byte[] MessageId; [DataMember(Name = "query_string")] - public string QueryString = ""; + public string QueryString; + + public OneOffQuery( + byte[] MessageId, + string QueryString + ) + { + this.MessageId = MessageId; + this.QueryString = QueryString; + } + + public OneOffQuery() + { + this.MessageId = Array.Empty(); + this.QueryString = ""; + } } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs index 35c1d0eb907..f539516f6ed 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs @@ -17,13 +17,32 @@ namespace SpacetimeDB.ClientApi public partial class OneOffQueryResponse { [DataMember(Name = "message_id")] - public byte[] MessageId = Array.Empty(); + public byte[] MessageId; [DataMember(Name = "error")] public string? Error; [DataMember(Name = "tables")] - public System.Collections.Generic.List Tables = new(); + public System.Collections.Generic.List Tables; [DataMember(Name = "total_host_execution_duration_micros")] public ulong TotalHostExecutionDurationMicros; + public OneOffQueryResponse( + byte[] MessageId, + string? Error, + System.Collections.Generic.List Tables, + ulong TotalHostExecutionDurationMicros + ) + { + this.MessageId = MessageId; + this.Error = Error; + this.Tables = Tables; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + } + + public OneOffQueryResponse() + { + this.MessageId = Array.Empty(); + this.Tables = new(); + } + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs index 12f7e0f9d2b..d1f48f3f942 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs @@ -17,9 +17,24 @@ namespace SpacetimeDB.ClientApi public partial class OneOffTable { [DataMember(Name = "table_name")] - public string TableName = ""; + public string TableName; [DataMember(Name = "rows")] - public System.Collections.Generic.List Rows = new(); + public SpacetimeDB.ClientApi.BsatnRowList Rows; + + public OneOffTable( + string TableName, + SpacetimeDB.ClientApi.BsatnRowList Rows + ) + { + this.TableName = TableName; + this.Rows = Rows; + } + + public OneOffTable() + { + this.TableName = ""; + this.Rows = new(); + } } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs new file mode 100644 index 00000000000..858dea65244 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs @@ -0,0 +1,40 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class QueryUpdate + { + [DataMember(Name = "deletes")] + public SpacetimeDB.ClientApi.BsatnRowList Deletes; + [DataMember(Name = "inserts")] + public SpacetimeDB.ClientApi.BsatnRowList Inserts; + + public QueryUpdate( + SpacetimeDB.ClientApi.BsatnRowList Deletes, + SpacetimeDB.ClientApi.BsatnRowList Inserts + ) + { + this.Deletes = Deletes; + this.Inserts = Inserts; + } + + public QueryUpdate() + { + this.Deletes = new(); + this.Inserts = new(); + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs index 44bc88654c5..0ca52252667 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs @@ -17,13 +17,32 @@ namespace SpacetimeDB.ClientApi public partial class ReducerCallInfo { [DataMember(Name = "reducer_name")] - public string ReducerName = ""; + public string ReducerName; [DataMember(Name = "reducer_id")] public uint ReducerId; [DataMember(Name = "args")] - public SpacetimeDB.ClientApi.EncodedValue Args = null!; + public byte[] Args; [DataMember(Name = "request_id")] public uint RequestId; + public ReducerCallInfo( + string ReducerName, + uint ReducerId, + byte[] Args, + uint RequestId + ) + { + this.ReducerName = ReducerName; + this.ReducerId = ReducerId; + this.Args = Args; + this.RequestId = RequestId; + } + + public ReducerCallInfo() + { + this.ReducerName = ""; + this.Args = Array.Empty(); + } + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs similarity index 66% rename from sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs rename to sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs index 16793ca5a30..71c04c1b956 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EncodedValue.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs @@ -10,8 +10,8 @@ namespace SpacetimeDB.ClientApi { [SpacetimeDB.Type] - public partial record EncodedValue : SpacetimeDB.TaggedEnum<( - byte[] Binary, - string Text + public partial record RowSizeHint : SpacetimeDB.TaggedEnum<( + ushort FixedSize, + System.Collections.Generic.List RowOffsets )>; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs index d5eaba815a2..0adad9b285c 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs @@ -17,9 +17,23 @@ namespace SpacetimeDB.ClientApi public partial class Subscribe { [DataMember(Name = "query_strings")] - public System.Collections.Generic.List QueryStrings = new(); + public System.Collections.Generic.List QueryStrings; [DataMember(Name = "request_id")] public uint RequestId; + public Subscribe( + System.Collections.Generic.List QueryStrings, + uint RequestId + ) + { + this.QueryStrings = QueryStrings; + this.RequestId = RequestId; + } + + public Subscribe() + { + this.QueryStrings = new(); + } + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs index b9b47ea5d91..cc2586d3ccd 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs @@ -19,11 +19,30 @@ public partial class TableUpdate [DataMember(Name = "table_id")] public uint TableId; [DataMember(Name = "table_name")] - public string TableName = ""; - [DataMember(Name = "deletes")] - public System.Collections.Generic.List Deletes = new(); - [DataMember(Name = "inserts")] - public System.Collections.Generic.List Inserts = new(); + public string TableName; + [DataMember(Name = "num_rows")] + public ulong NumRows; + [DataMember(Name = "updates")] + public System.Collections.Generic.List Updates; + + public TableUpdate( + uint TableId, + string TableName, + ulong NumRows, + System.Collections.Generic.List Updates + ) + { + this.TableId = TableId; + this.TableName = TableName; + this.NumRows = NumRows; + this.Updates = Updates; + } + + public TableUpdate() + { + this.TableName = ""; + this.Updates = new(); + } } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs index 4dd2535c26b..c0f53ba1a95 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs @@ -19,5 +19,16 @@ public partial class Timestamp [DataMember(Name = "microseconds")] public ulong Microseconds; + public Timestamp( + ulong Microseconds + ) + { + this.Microseconds = Microseconds; + } + + public Timestamp() + { + } + } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs index fb71dd9e318..e4925bf40e9 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs @@ -17,19 +17,48 @@ namespace SpacetimeDB.ClientApi public partial class TransactionUpdate { [DataMember(Name = "status")] - public SpacetimeDB.ClientApi.UpdateStatus Status = null!; + public SpacetimeDB.ClientApi.UpdateStatus Status; [DataMember(Name = "timestamp")] - public SpacetimeDB.ClientApi.Timestamp Timestamp = new(); + public SpacetimeDB.ClientApi.Timestamp Timestamp; [DataMember(Name = "caller_identity")] - public SpacetimeDB.Identity CallerIdentity = new(); + public SpacetimeDB.Identity CallerIdentity; [DataMember(Name = "caller_address")] - public SpacetimeDB.Address CallerAddress = new(); + public SpacetimeDB.Address CallerAddress; [DataMember(Name = "reducer_call")] - public SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall = new(); + public SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall; [DataMember(Name = "energy_quanta_used")] - public SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed = new(); + public SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed; [DataMember(Name = "host_execution_duration_micros")] public ulong HostExecutionDurationMicros; + public TransactionUpdate( + SpacetimeDB.ClientApi.UpdateStatus Status, + SpacetimeDB.ClientApi.Timestamp Timestamp, + SpacetimeDB.Identity CallerIdentity, + SpacetimeDB.Address CallerAddress, + SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall, + SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed, + ulong HostExecutionDurationMicros + ) + { + this.Status = Status; + this.Timestamp = Timestamp; + this.CallerIdentity = CallerIdentity; + this.CallerAddress = CallerAddress; + this.ReducerCall = ReducerCall; + this.EnergyQuantaUsed = EnergyQuantaUsed; + this.HostExecutionDurationMicros = HostExecutionDurationMicros; + } + + public TransactionUpdate() + { + this.Status = null!; + this.Timestamp = new(); + this.CallerIdentity = new(); + this.CallerAddress = new(); + this.ReducerCall = new(); + this.EnergyQuantaUsed = new(); + } + } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 88c85cccee4..c01bb9b963a 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -144,7 +144,7 @@ protected DbConnectionBase() { //v1.bin.spacetimedb //v1.text.spacetimedb - Protocol = "v1.bin.spacetimedb", + Protocol = "v1.bsatn.spacetimedb" }; webSocket = new WebSocket(options); webSocket.OnMessage += OnMessageReceived; @@ -185,10 +185,8 @@ struct PreProcessedMessage private readonly CancellationTokenSource _preProcessCancellationTokenSource = new(); private CancellationToken _preProcessCancellationToken => _preProcessCancellationTokenSource.Token; - static DbValue Decode(IRemoteTableHandle table, EncodedValue value, out object? primaryKey) + static DbValue Decode(IRemoteTableHandle table, byte[] bin, out object? primaryKey) { - // We expect only binary messages here; let type cast exception take care of any others. - var bin = ((EncodedValue.Binary)value).Binary_; var obj = table.DecodeValue(bin); primaryKey = table.GetPrimaryKey(obj); return new(obj, bin); @@ -197,6 +195,104 @@ static DbValue Decode(IRemoteTableHandle table, EncodedValue value, out object? private static readonly Status Committed = new Status.Committed(default); private static readonly Status OutOfEnergy = new Status.OutOfEnergy(default); + enum CompressionAlgos : byte + { + None = 0, + Brotli = 1, + } + + private static ServerMessage DecompressDecodeMessage(byte[] bytes) + { + using var stream = new MemoryStream(bytes, 1, bytes.Length - 1); + + // The stream will never be empty. It will at least contain the compression algo. + var compression = (CompressionAlgos)bytes[0]; + // Conditionally decompress and decode. + switch (compression) + { + case CompressionAlgos.None: + { + using var binaryReader = new BinaryReader(stream); + return new ServerMessage.BSATN().Read(binaryReader); + } + case CompressionAlgos.Brotli: + { + using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); + using var binaryReader = new BinaryReader(decompressedStream); + return new ServerMessage.BSATN().Read(binaryReader); + } + default: + throw new InvalidOperationException("Unknown compression type"); + } + } + + private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate update) + { + switch (update) + { + case CompressableQueryUpdate.Uncompressed(var qu): + return qu; + + case CompressableQueryUpdate.Brotli(var bytes): + { + using var stream = new MemoryStream(bytes); + using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); + using var binaryReader = new BinaryReader(decompressedStream); + return new QueryUpdate.BSATN().Read(binaryReader); + } + default: + throw new InvalidOperationException(); + } + } + + private static int BsatnRowListCount(BsatnRowList list) + { + switch (list.SizeHint) + { + case RowSizeHint.FixedSize(var size): + return list.RowsData.Length / size; + case RowSizeHint.RowOffsets(var offsets): + return offsets.Count; + default: + throw new InvalidOperationException("Unknown RowSizeHint variant"); + } + } + + private static IEnumerable BsatnRowListIter(BsatnRowList list) + { + var count = BsatnRowListCount(list); + for (int index = 0; index < count; index += 1) + { + switch (list.SizeHint) + { + case RowSizeHint.FixedSize(var size): + { + int start = index * size; + int elemLen = size; + yield return new ReadOnlySpan(list.RowsData, start, elemLen).ToArray(); + break; + } + case RowSizeHint.RowOffsets(var offsets): + { + int start = (int)offsets[index]; + // The end is either the start of the next element or the end. + int end; + if (index + 1 == count) + { + end = list.RowsData.Length; + } + else + { + end = (int)offsets[index + 1]; + } + int elemLen = end - start; + yield return new ReadOnlyMemory(list.RowsData, start, elemLen).ToArray(); + break; + } + } + } + } + void PreProcessMessages() { while (!isClosing) @@ -216,10 +312,8 @@ void PreProcessMessages() PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) { var dbOps = new List(); - using var compressedStream = new MemoryStream(unprocessed.bytes); - using var decompressedStream = new BrotliStream(compressedStream, CompressionMode.Decompress); - using var binaryReader = new BinaryReader(decompressedStream); - var message = new ServerMessage.BSATN().Read(binaryReader); + + var message = DecompressDecodeMessage(unprocessed.bytes); ReducerEvent? reducerEvent = default; @@ -242,7 +336,8 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) switch (message) { case ServerMessage.InitialSubscription(var initialSubscription): - subscriptionInserts = new(capacity: initialSubscription.DatabaseUpdate.Tables.Sum(a => a.Inserts.Count)); + int cap = initialSubscription.DatabaseUpdate.Tables.Sum(a => (int)a.NumRows); + subscriptionInserts = new(capacity: cap); // First apply all of the state foreach (var update in initialSubscription.DatabaseUpdate.Tables) @@ -255,37 +350,33 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) continue; } - if (update.Deletes.Count != 0) - { - Log.Warn("Non-insert during a subscription update!"); - } - - var hashSet = GetInsertHashSet(table.ClientTableType, initialSubscription.DatabaseUpdate.Tables.Count); + var hashSet = GetInsertHashSet(table.ClientTableType, (int)update.NumRows); - foreach (var row in update.Inserts) + foreach (var cqu in update.Updates) { - switch (row) + var qu = DecompressDecodeQueryUpdate(cqu); + if (BsatnRowListCount(qu.Deletes) != 0) { - case EncodedValue.Binary(var bin): - if (!hashSet.Add(bin)) - { - // Ignore duplicate inserts in the same subscription update. - continue; - } + Log.Warn("Non-insert during a subscription update!"); + } - var obj = table.DecodeValue(bin); - var op = new DbOp - { - table = table, - insert = new(obj, bin), - }; + foreach (var bin in BsatnRowListIter(qu.Inserts)) + { + if (!hashSet.Add(bin)) + { + // Ignore duplicate inserts in the same subscription update. + continue; + } - dbOps.Add(op); - break; + var obj = table.DecodeValue(bin); + var op = new DbOp + { + table = table, + insert = new(obj, bin), + }; - case EncodedValue.Text(var txt): - Log.Warn("JavaScript messages are unsupported."); - break; + dbOps.Add(op); + break; } } } @@ -329,73 +420,77 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) continue; } - foreach (var row in update.Inserts) + foreach (var cqu in update.Updates) { - var op = new DbOp { table = table, insert = Decode(table, row, out var pk) }; - if (pk != null) + var qu = DecompressDecodeQueryUpdate(cqu); + foreach (var row in BsatnRowListIter(qu.Inserts)) { - // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, pk); - - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) + var op = new DbOp { table = table, insert = Decode(table, row, out var pk) }; + if (pk != null) { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) - { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; - } + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, pk); - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - op = new DbOp + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) + { + Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. + continue; + } + + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + op = new DbOp + { + table = insertOp.table, + delete = deleteOp.delete, + insert = insertOp.insert, + }; + } + primaryKeyChanges[key] = op; + } + else + { + dbOps.Add(op); } - primaryKeyChanges[key] = op; - } - else - { - dbOps.Add(op); } - } - foreach (var row in update.Deletes) - { - var op = new DbOp { table = table, delete = Decode(table, row, out var pk) }; - if (pk != null) + foreach (var row in BsatnRowListIter(qu.Deletes)) { - // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, pk); - - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) + var op = new DbOp { table = table, delete = Decode(table, row, out var pk) }; + if (pk != null) { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) - { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; - } + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, pk); - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - op = new DbOp + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) + { + Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. + continue; + } + + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + op = new DbOp + { + table = insertOp.table, + delete = deleteOp.delete, + insert = insertOp.insert, + }; + } + primaryKeyChanges[key] = op; + } + else + { + dbOps.Add(op); } - primaryKeyChanges[key] = op; - } - else - { - dbOps.Add(op); } } } @@ -702,7 +797,7 @@ public void InternalCallReducer(T args) { RequestId = stats.ReducerRequestTracker.StartTrackingRequest(args.ReducerName), Reducer = args.ReducerName, - Args = new EncodedValue.Binary(IStructuralReadWrite.ToBytes(args)) + Args = IStructuralReadWrite.ToBytes(args) } )); } @@ -780,7 +875,9 @@ T[] LogAndThrow(string error) return LogAndThrow($"Mismatched result type, expected {type} but got {resultTable.TableName}"); } - return resultTable.Rows.Select(BSATNHelpers.Decode).ToArray(); + return BsatnRowListIter(resultTable.Rows) + .Select(row => BSATNHelpers.Decode(row)) + .ToArray(); } public bool IsActive => webSocket.IsConnected; diff --git a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt index 513aa66c49d..53528975301 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -390,4 +390,4 @@ Max: type=InitialSubscription } } -} \ No newline at end of file +} diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index dd08dfe6a86..c429d07bfd9 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -47,14 +47,6 @@ public override void Write(VerifyJsonWriter writer, EnergyQuanta value) } } - class EncodedValueConverter : WriteOnlyJsonConverter - { - public override void Write(VerifyJsonWriter writer, EncodedValue.Binary value) - { - writer.WriteValue(value.Binary_); - } - } - class TestLogger(Events events) : ISpacetimeDBLogger { public void Debug(string message) @@ -124,7 +116,7 @@ private static ServerMessage.TransactionUpdate SampleTransactionUpdate( ulong energyQuantaUsed, ulong hostExecutionDuration, List updates, - EncodedValue? args + byte[]? args ) => new(new() { Timestamp = new Timestamp { Microseconds = timestamp }, @@ -139,7 +131,7 @@ private static ServerMessage.TransactionUpdate SampleTransactionUpdate( { RequestId = requestId, ReducerName = reducerName, - Args = args ?? new EncodedValue.Binary([]) + Args = args ?? [] }, Status = new UpdateStatus.Committed(new() { @@ -147,55 +139,73 @@ private static ServerMessage.TransactionUpdate SampleTransactionUpdate( }) }); - private static TableUpdate SampleUpdate( + private static TableUpdate SampleUpdate( uint tableId, string tableName, - List inserts, - List deletes - ) => new() + List inserts, + List deletes + ) where T : IStructuralReadWrite => new() { TableId = tableId, TableName = tableName, - Inserts = inserts, - Deletes = deletes + NumRows = (ulong)(inserts.Count + deletes.Count), + Updates = [new CompressableQueryUpdate.Uncompressed(new QueryUpdate( + EncodeRowList(deletes), EncodeRowList(inserts)))] }; - private static EncodedValue.Binary Encode(in T value) where T : IStructuralReadWrite + private static BsatnRowList EncodeRowList(in List list) where T : IStructuralReadWrite + { + var offsets = new List(); + var stream = new MemoryStream(); + var writer = new BinaryWriter(stream); + foreach (var elem in list) + { + offsets.Add((ulong)stream.Length); + elem.WriteFields(writer); + } + return new BsatnRowList + { + RowsData = stream.ToArray(), + SizeHint = new RowSizeHint.RowOffsets(offsets) + }; + } + + private static byte[] Encode(in T value) where T : IStructuralReadWrite { var o = new MemoryStream(); var w = new BinaryWriter(o); value.WriteFields(w); - return new EncodedValue.Binary(o.ToArray()); + return o.ToArray(); } private static TableUpdate SampleUserInsert(string identity, string? name, bool online) => - SampleUpdate(4097, "User", [Encode(new User + SampleUpdate(4097, "User", [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = name, Online = online - })], []); + }], []); private static TableUpdate SampleUserUpdate(string identity, string? oldName, string? newName, bool oldOnline, bool newOnline) => - SampleUpdate(4097, "User", [Encode(new User + SampleUpdate(4097, "User", [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = newName, Online = newOnline - })], [Encode(new User + }], [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = oldName, Online = oldOnline - })]); + }]); private static TableUpdate SampleMessage(string identity, ulong sent, string text) => - SampleUpdate(4098, "Message", [Encode(new Message + SampleUpdate(4098, "Message", [new Message { Sender = Identity.From(Convert.FromBase64String(identity)), Sent = sent, Text = text - })], []); + }], []); private static ServerMessage[] SampleDump() => [ SampleId( @@ -282,6 +292,7 @@ public async Task VerifyAllTablesParsed() break; } using var output = new MemoryStream(); + output.WriteByte(1); // Write compression tag. using (var brotli = new BrotliStream(output, CompressionMode.Compress)) { using var w = new BinaryWriter(brotli); @@ -346,8 +357,7 @@ await Verify( .AddExtraSettings(settings => settings.Converters.AddRange([ new EventsConverter(), new TimestampConverter(), - new EnergyQuantaConverter(), - new EncodedValueConverter() + new EnergyQuantaConverter() ])) .ScrubMember(x => x.Status) .ScrubMember>(x => x.Db) From cec6fb815a57631e2e7472648145ddf4496921ba Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 2 Oct 2024 21:56:57 +0100 Subject: [PATCH 118/223] Fix UnityDebugLogger implementation (#143) ## Description of Changes Without explicit reference these result in > error CS0119: 'UnityDebugLogger.Debug(string)' is a method, which is not valid in the given context ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/UnityDebugLogger.cs | 43 ++++++++++------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/sdks/csharp/src/UnityDebugLogger.cs b/sdks/csharp/src/UnityDebugLogger.cs index 218cde182e0..94d21aee8a4 100644 --- a/sdks/csharp/src/UnityDebugLogger.cs +++ b/sdks/csharp/src/UnityDebugLogger.cs @@ -4,46 +4,31 @@ */ #if UNITY_5_3_OR_NEWER using System; -using UnityEngine; namespace SpacetimeDB { internal class UnityDebugLogger : ISpacetimeDBLogger { - public void Debug(string message) - { - Debug.Log(message); - } + public void Debug(string message) => + UnityEngine.Debug.Log(message); - public void Trace(string message) - { - Debug.Log(message); - } + public void Trace(string message) => + UnityEngine.Debug.Log(message); - public void Info(string message) - { - Debug.Log(message); - } + public void Info(string message) => + UnityEngine.Debug.Log(message); - public void Warn(string message) - { - Debug.LogWarning(message); - } + public void Warn(string message) => + UnityEngine.Debug.LogWarning(message); - public void Error(string message) - { - Debug.LogError(message); - } + public void Error(string message) => + UnityEngine.Debug.LogError(message); - public void Exception(string message) - { - Debug.LogError(message); - } + public void Exception(string message) => + UnityEngine.Debug.LogError(message); - public void Exception(Exception e) - { - Debug.LogException(e); - } + public void Exception(Exception e) => + UnityEngine.Debug.LogException(e); } } #endif From 463a240f4546f612b723586a946c9306df3c02e7 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 2 Oct 2024 22:52:03 +0100 Subject: [PATCH 119/223] Tighten package sources in C# smoketests (#133) ## Description of Changes Same as https://github.com/clockworklabs/SpacetimeDB/pull/1735 but for this repo. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/.github/workflows/dotnet.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml index 9733140e806..69d6b8b18d6 100644 --- a/sdks/csharp/.github/workflows/dotnet.yml +++ b/sdks/csharp/.github/workflows/dotnet.yml @@ -44,9 +44,18 @@ jobs: - - + + + + + + + + + + + EOF - name: Restore dependencies From 9d3336e6f5fadad4db1b07ea2657b0dcf2e5b567 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 3 Oct 2024 00:18:06 +0100 Subject: [PATCH 120/223] Reduce public API surface further (#145) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [x] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/BSATNHelpers.cs | 18 ++---------------- sdks/csharp/src/ISpacetimeDBLogger.cs | 4 ++-- sdks/csharp/src/SpacetimeDBClient.cs | 1 + sdks/csharp/src/Stats.cs | 18 +++++++++--------- 4 files changed, 14 insertions(+), 27 deletions(-) diff --git a/sdks/csharp/src/BSATNHelpers.cs b/sdks/csharp/src/BSATNHelpers.cs index 46c4cb6443e..9c227e13171 100644 --- a/sdks/csharp/src/BSATNHelpers.cs +++ b/sdks/csharp/src/BSATNHelpers.cs @@ -1,29 +1,15 @@ -using System; using SpacetimeDB.BSATN; using System.IO; -using SpacetimeDB.ClientApi; namespace SpacetimeDB { public static class BSATNHelpers { - public static T FromStream(Stream stream) - where T : IStructuralReadWrite, new() - { - using var reader = new BinaryReader(stream); - return IStructuralReadWrite.Read(reader); - } - public static T Decode(byte[] bsatn) where T : IStructuralReadWrite, new() { using var stream = new MemoryStream(bsatn); - return FromStream(stream); - } - - public static T Decode(string json) - where T : IStructuralReadWrite, new() - { - throw new InvalidOperationException("JSON isn't supported at the moment"); + using var reader = new BinaryReader(stream); + return IStructuralReadWrite.Read(reader); } } } diff --git a/sdks/csharp/src/ISpacetimeDBLogger.cs b/sdks/csharp/src/ISpacetimeDBLogger.cs index 5223a62868b..e8f01cecf07 100644 --- a/sdks/csharp/src/ISpacetimeDBLogger.cs +++ b/sdks/csharp/src/ISpacetimeDBLogger.cs @@ -2,7 +2,7 @@ namespace SpacetimeDB { - public interface ISpacetimeDBLogger + internal interface ISpacetimeDBLogger { void Debug(string message); void Trace(string message); @@ -15,7 +15,7 @@ public interface ISpacetimeDBLogger public static class Log { - public static ISpacetimeDBLogger Current = + internal static ISpacetimeDBLogger Current = #if UNITY_5_3_OR_NEWER new UnityDebugLogger(); diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index c01bb9b963a..48b760861f4 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -783,6 +783,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) internal void OnMessageReceived(byte[] bytes, DateTime timestamp) => _messageQueue.Add(new UnprocessedMessage { bytes = bytes, timestamp = timestamp }); + // TODO: this should become [Obsolete] but for now is used by autogenerated code. public void InternalCallReducer(T args) where T : IReducerArgs, new() { diff --git a/sdks/csharp/src/Stats.cs b/sdks/csharp/src/Stats.cs index 0d0ff3fcc51..bac011d0b82 100644 --- a/sdks/csharp/src/Stats.cs +++ b/sdks/csharp/src/Stats.cs @@ -12,7 +12,7 @@ public class NetworkRequestTracker private uint _nextRequestId; private readonly Dictionary _requests = new(); - public uint StartTrackingRequest(string metadata = "") + internal uint StartTrackingRequest(string metadata = "") { // Record the start time of the request var newRequestId = ++_nextRequestId; @@ -20,7 +20,7 @@ public uint StartTrackingRequest(string metadata = "") return newRequestId; } - public bool FinishTrackingRequest(uint requestId) + internal bool FinishTrackingRequest(uint requestId) { if (!_requests.Remove(requestId, out var entry)) { @@ -40,12 +40,12 @@ public bool FinishTrackingRequest(uint requestId) return true; } - public void InsertRequest(TimeSpan duration, string metadata) + internal void InsertRequest(TimeSpan duration, string metadata) { _requestDurations.Enqueue((DateTime.UtcNow, duration, metadata)); } - public void InsertRequest(DateTime start, string metadata) + internal void InsertRequest(DateTime start, string metadata) { InsertRequest(DateTime.UtcNow - start, metadata); } @@ -69,10 +69,10 @@ public void InsertRequest(DateTime start, string metadata) public class Stats { - public NetworkRequestTracker ReducerRequestTracker = new(); - public NetworkRequestTracker OneOffRequestTracker = new(); - public NetworkRequestTracker SubscriptionRequestTracker = new(); - public NetworkRequestTracker AllReducersTracker = new(); - public NetworkRequestTracker ParseMessageTracker = new(); + public readonly NetworkRequestTracker ReducerRequestTracker = new(); + public readonly NetworkRequestTracker OneOffRequestTracker = new(); + public readonly NetworkRequestTracker SubscriptionRequestTracker = new(); + public readonly NetworkRequestTracker AllReducersTracker = new(); + public readonly NetworkRequestTracker ParseMessageTracker = new(); } } From fa87e3630804f8ae577f7fd21dd902a88bed323a Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 3 Oct 2024 00:19:12 +0100 Subject: [PATCH 121/223] Don't actually try to connect to network in tests (#144) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/SpacetimeDBClient.cs | 31 ++++++++++++++-------------- sdks/csharp/tests~/SnapshotTests.cs | 2 ++ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 48b760861f4..e8d815c9fbb 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -11,9 +11,6 @@ using SpacetimeDB.Internal; using SpacetimeDB.ClientApi; using Thread = System.Threading.Thread; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("SpacetimeDB.Tests")] namespace SpacetimeDB { @@ -180,6 +177,7 @@ struct PreProcessedMessage private readonly BlockingCollection _preProcessedNetworkMessages = new(new ConcurrentQueue()); + internal static bool IsTesting; internal bool HasPreProcessedMessage => _preProcessedNetworkMessages.Count > 0; private readonly CancellationTokenSource _preProcessCancellationTokenSource = new(); @@ -582,23 +580,26 @@ internal void Connect(string? token, string uri, string addressOrName) } Log.Info($"SpacetimeDBClient: Connecting to {uri} {addressOrName}"); - Task.Run(async () => + if (!IsTesting) { - try - { - await webSocket.Connect(token, uri, addressOrName, Address); - } - catch (Exception e) + Task.Run(async () => { - if (connectionClosed) + try { - Log.Info("Connection closed gracefully."); - return; + await webSocket.Connect(token, uri, addressOrName, Address); } + catch (Exception e) + { + if (connectionClosed) + { + Log.Info("Connection closed gracefully."); + return; + } - Log.Exception(e); - } - }); + Log.Exception(e); + } + }); + } } private void OnMessageProcessCompleteUpdate(IEventContext eventContext, List dbOps) diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index c429d07bfd9..079644d168c 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -268,6 +268,8 @@ public async Task VerifyAllTablesParsed() Log.Current = new TestLogger(events); + DbConnection.IsTesting = true; + var client = DbConnection.Builder() .WithUri("wss://spacetimedb.com") From affa2af7dbd54ebd5ba7228aa7831922d282f4f5 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 3 Oct 2024 05:03:29 -0700 Subject: [PATCH 122/223] Add script to generate `nuget.config` (#115) ## Description of Changes Adds a utility script to generate `nuget.config` given a path to the `SpacetimeDB` repo. ## API No ## Requires SpacetimeDB PRs None ## Testing - [x] CI - [x] Ran locally --------- Co-authored-by: Zeke Foppa --- sdks/csharp/.github/workflows/dotnet.yml | 25 ++--------------- sdks/csharp/tests~/README.md | 20 ++++++++++++++ sdks/csharp/tools~/write-nuget-config.sh | 35 ++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 22 deletions(-) create mode 100644 sdks/csharp/tests~/README.md create mode 100755 sdks/csharp/tools~/write-nuget-config.sh diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml index 69d6b8b18d6..643a162892d 100644 --- a/sdks/csharp/.github/workflows/dotnet.yml +++ b/sdks/csharp/.github/workflows/dotnet.yml @@ -36,28 +36,9 @@ jobs: # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. # This means that (if version numbers match) we will test the local versions of the C# packages, even # if they're not pushed to NuGet. - # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file, - # and https://tldp.org/LDP/abs/html/here-docs.html for more info on this bash feature. - cat >nuget.config < - - - - - - - - - - - - - - - - - - EOF + # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. + ./tools~/write-nuget-config.sh ../SpacetimeDB + - name: Restore dependencies working-directory: spacetimedb-csharp-sdk run: dotnet restore diff --git a/sdks/csharp/tests~/README.md b/sdks/csharp/tests~/README.md new file mode 100644 index 00000000000..95f9a400393 --- /dev/null +++ b/sdks/csharp/tests~/README.md @@ -0,0 +1,20 @@ +# Running tests +You can use `dotnet test` (either in this directory or in the project root directory) to run the tests. + +# Using a different SpacetimeDB version +To run tests using a local version of the `SpacetimeDB` repo, you can add a `nuget.config` file in the **root** of this repository. + +The `tools/write-nuget-config.sh` script can generate the `nuget.config`. It takes one parameter: the path to the root SpacetimeDB repository (relative or absolute). + +Then, you need to `dotnet pack` the `BSATN.Runtime` package in the `SpacetimeDB` repo. + +Lastly, before running `dotnet test`, you should `dotnet nuget locals all --clear` to clear out any cached packages. This ensures you're actually testing with the new package you just built. + +Example: +```bash +$ export SPACETIMEDB_REPO_PATH="../SpacetimeDB" +$ tools/write-nuget-config.sh "${SPACETIMEDB_REPO_PATH}" +$ ( cd "${SPACETIMEDB_REPO_PATH}"/crates/bindings-csharp/BSATN.Runtime && dotnet pack ) +$ dotnet nuget locals all --clear +$ dotnet test +``` diff --git a/sdks/csharp/tools~/write-nuget-config.sh b/sdks/csharp/tools~/write-nuget-config.sh new file mode 100755 index 00000000000..1655fc96bff --- /dev/null +++ b/sdks/csharp/tools~/write-nuget-config.sh @@ -0,0 +1,35 @@ +set -ueo pipefail + +SPACETIMEDB_REPO_PATH="$1" + +cd "$(dirname "$(readlink -f "$0")")" +cd .. + +# Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository +# to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if +# available. +# See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file, +# and https://tldp.org/LDP/abs/html/here-docs.html for more info on this bash feature. +cat >nuget.config < + + + + + + + + + + + + + + + + + +EOF + +echo "Wrote nuget.config contents:" +cat nuget.config From b96f1a6cd5fcf8dae410f116bfd7a392fb1206df Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 3 Oct 2024 09:48:54 -0700 Subject: [PATCH 123/223] Fix `gen-client-api` scripts for new CLI API (#151) ## Description of Changes The CLI arg changes in https://github.com/clockworklabs/SpacetimeDB/pull/1741 broke these scripts. This PR incorporates the param renames. ## API No changes to how things are used. ## Requires SpacetimeDB PRs I guess https://github.com/clockworklabs/SpacetimeDB/pull/1741 --------- Co-authored-by: Zeke Foppa --- sdks/csharp/tools~/gen-client-api.bat | 4 ++-- sdks/csharp/tools~/gen-client-api.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/tools~/gen-client-api.bat b/sdks/csharp/tools~/gen-client-api.bat index 9eb66c49cdc..23196f94b72 100644 --- a/sdks/csharp/tools~/gen-client-api.bat +++ b/sdks/csharp/tools~/gen-client-api.bat @@ -10,8 +10,8 @@ cd %CL_HOME%\SpacetimeDB\crates\client-api-messages cargo run --example get_ws_schema > %CL_HOME%/schema.json cd %CL_HOME%\SpacetimeDB\crates\cli -cargo run -- generate -l csharp -n SpacetimeDB.ClientApi ^ - --json-module %CL_HOME%\schema.json ^ +cargo run -- generate -l csharp --namespace SpacetimeDB.ClientApi ^ + --module-def %CL_HOME%\schema.json ^ -o %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi cd %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi diff --git a/sdks/csharp/tools~/gen-client-api.sh b/sdks/csharp/tools~/gen-client-api.sh index 91fbe3dab83..5f118176a08 100644 --- a/sdks/csharp/tools~/gen-client-api.sh +++ b/sdks/csharp/tools~/gen-client-api.sh @@ -5,8 +5,8 @@ cd $CL_HOME/SpacetimeDB/crates/client-api-messages cargo run --example get_ws_schema > $CL_HOME/schema.json cd $CL_HOME/SpacetimeDB/crates/cli -cargo run -- generate -l csharp -n SpacetimeDB.ClientApi \ - --json-module $CL_HOME/schema.json \ +cargo run -- generate -l csharp --namespace SpacetimeDB.ClientApi \ + --module-def $CL_HOME/schema.json \ -o $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi cd $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi From 76d275f1b559db52f5a7db2041a684a25d5c93f0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 3 Oct 2024 18:13:59 +0100 Subject: [PATCH 124/223] Remove obsolete tools folder (#149) ## Description of Changes Not sure when or how this was added (it's not on master), but this folder shouldn't be here - we have `tools~` instead. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/tools/gen-client-api.bat | 20 -------------------- sdks/csharp/tools/gen-client-api.sh | 15 --------------- 2 files changed, 35 deletions(-) delete mode 100644 sdks/csharp/tools/gen-client-api.bat delete mode 100644 sdks/csharp/tools/gen-client-api.sh diff --git a/sdks/csharp/tools/gen-client-api.bat b/sdks/csharp/tools/gen-client-api.bat deleted file mode 100644 index 9eb66c49cdc..00000000000 --- a/sdks/csharp/tools/gen-client-api.bat +++ /dev/null @@ -1,20 +0,0 @@ -@echo off -setlocal - -if "%CL_HOME%"=="" ( - echo "Variable CL_HOME not set" - exit /b 1 -) - -cd %CL_HOME%\SpacetimeDB\crates\client-api-messages -cargo run --example get_ws_schema > %CL_HOME%/schema.json - -cd %CL_HOME%\SpacetimeDB\crates\cli -cargo run -- generate -l csharp -n SpacetimeDB.ClientApi ^ - --json-module %CL_HOME%\schema.json ^ - -o %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi - -cd %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi -del /q _Globals - -del %CL_HOME%\schema.json diff --git a/sdks/csharp/tools/gen-client-api.sh b/sdks/csharp/tools/gen-client-api.sh deleted file mode 100644 index 91fbe3dab83..00000000000 --- a/sdks/csharp/tools/gen-client-api.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -eu -: $CL_HOME - -cd $CL_HOME/SpacetimeDB/crates/client-api-messages -cargo run --example get_ws_schema > $CL_HOME/schema.json - -cd $CL_HOME/SpacetimeDB/crates/cli -cargo run -- generate -l csharp -n SpacetimeDB.ClientApi \ - --json-module $CL_HOME/schema.json \ - -o $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi - -cd $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi -rm -rf _Globals - -rm -f $CL_HOME/schema.json From 2c95bee7b2c7a7f1cc42b8d90d547680983dee55 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 3 Oct 2024 18:17:06 +0100 Subject: [PATCH 125/223] Try to catch flaky bugs (#150) ## Description of Changes We have some flaky bug where Events are getting modified while we're already iterating over them in the snapshot. I think this might've been fixed by #144, but add extra checks just in case so that the exception is thrown in a concrete event that causes it, and not inside snapshot serialization. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/tests~/SnapshotTests.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 079644d168c..8e99242e456 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -12,10 +12,21 @@ public class SnapshotTests { class Events : List> { + private bool frozen; + public void Add(string name, object? value = null) { + if (frozen) + { + throw new InvalidOperationException("This is a bug. We have snapshotted the events and don't expect any more to arrive."); + } base.Add(new(name, value)); } + + public void Freeze() + { + frozen = true; + } } class EventsConverter : WriteOnlyJsonConverter @@ -344,6 +355,7 @@ public async Task VerifyAllTablesParsed() } // Verify dumped events and the final client state. + events.Freeze(); await Verify( new { From 1b0e843a9842815b1df39c1e4a10be2fd089198b Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Thu, 3 Oct 2024 19:00:10 -0400 Subject: [PATCH 126/223] Jeremie/remove break (#154) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- sdks/csharp/src/SpacetimeDBClient.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index e8d815c9fbb..11237718873 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -374,7 +374,6 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) }; dbOps.Add(op); - break; } } } From b320e5ec586db9d95dfb69d18c756710da0701cb Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 3 Oct 2024 16:31:14 -0700 Subject: [PATCH 127/223] Update DLLs for 0.12.0 (#152) ## Description of Changes Updated the DLLs for 0.12.0 from the PR: ``` commit 0a7512d2a8db0dcff05aaee92f260e53d71cdc80 (HEAD -> release/v0.12.0-beta, origin/release/v0.12.0-beta) Author: Zeke Foppa Date: Thu Oct 3 09:35:27 2024 -0700 [release/v0.12.0-beta]: Manually apply open PR #1707: c# client generate ``` ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --------- Co-authored-by: Zeke Foppa Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 47616 -> 0 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 52736 -> 0 bytes .../{0.11.0.meta => 0.12.0.meta} | 0 .../{0.11.0 => 0.12.0}/analyzers.meta | 0 .../{0.11.0 => 0.12.0}/analyzers/dotnet.meta | 0 .../{0.11.0 => 0.12.0}/analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 0 -> 57856 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{0.11.0 => 0.12.0}/lib.meta | 0 .../{0.11.0 => 0.12.0}/lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 68096 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 12 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll delete mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.11.0.meta => 0.12.0.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.11.0 => 0.12.0}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.11.0 => 0.12.0}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.11.0 => 0.12.0}/analyzers/dotnet/cs.meta (100%) create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.11.0 => 0.12.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.11.0 => 0.12.0}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.11.0 => 0.12.0}/lib/netstandard2.1.meta (100%) create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.11.0 => 0.12.0}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll deleted file mode 100644 index d56f1f0f232ba24dd9c18f50389b15e95ce0f0f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47616 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 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll deleted file mode 100644 index 0ef9930fd6d81bdeb798f061cb1c6288f05974c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52736 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 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll new file mode 100644 index 0000000000000000000000000000000000000000..222b592781a64e8c004ffecde831368d31b1689e GIT binary patch literal 57856 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

    l%BndM>hwQH}!EQ5utonaZ;egKMWKl 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.11.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta From 434c5ffd8abc09dd53ff03092531f8e980b6b6ff Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 4 Oct 2024 01:25:05 +0100 Subject: [PATCH 128/223] Accept multiple queries in Subscribe (#153) ## Description of Changes Turns out, we're not ready for single Subscribe per query, so bringing back this ability. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> --- sdks/csharp/src/Event.cs | 6 +++--- sdks/csharp/src/SpacetimeDBClient.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index ff687c0f329..b637e69857d 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -61,7 +61,7 @@ public SubscriptionBuilder OnError(Action callback) return this; } - public SubscriptionHandle Subscribe(string querySql) => new(conn, Applied, Error, querySql); + public SubscriptionHandle Subscribe(params string[] querySqls) => new(conn, Applied, Error, querySqls); } public interface ISubscriptionHandle @@ -80,10 +80,10 @@ void ISubscriptionHandle.OnApplied(IEventContext ctx) onApplied?.Invoke((EventContext)ctx); } - internal SubscriptionHandle(IDbConnection conn, Action? onApplied, Action? onError, string querySql) + internal SubscriptionHandle(IDbConnection conn, Action? onApplied, Action? onError, string[] querySqls) { this.onApplied = onApplied; - conn.Subscribe(this, querySql); + conn.Subscribe(this, querySqls); } public void Unsubscribe() => throw new NotImplementedException(); diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 11237718873..6aa22f9d867 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -76,7 +76,7 @@ public DbConnectionBuilder OnDisconnect(Action : IDbConnection @@ -803,7 +803,7 @@ public void InternalCallReducer(T args) )); } - void IDbConnection.Subscribe(ISubscriptionHandle handle, string query) + void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) { if (!webSocket.IsConnected) { @@ -817,7 +817,7 @@ void IDbConnection.Subscribe(ISubscriptionHandle handle, string query) new Subscribe { RequestId = id, - QueryStrings = { query } + QueryStrings = querySqls.ToList() } )); } From 2d20acd06e723575c7d198d93f360bd6267298bf Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 4 Oct 2024 01:35:51 +0100 Subject: [PATCH 129/223] Fix UnityNetworkManager (#141) This got broken when we switched to a new DbConnection API. Keep track of all the active connections and update/destroy them from a singleton game object. Fixes #134. Marked as a draft for now, because it's untested and because we're not yet sure that singleton for all connections as requested is the right approach. ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --------- Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> Co-authored-by: John Detter --- .../_Globals/UnityNetworkManager.cs | 21 --------- .../ClientApi/BsatnRowList.cs.meta | 11 +++++ .../ClientApi/CompressableQueryUpdate.cs.meta | 11 +++++ .../SpacetimeDB/ClientApi/QueryUpdate.cs.meta | 11 +++++ .../SpacetimeDB/ClientApi/RowSizeHint.cs.meta | 11 +++++ sdks/csharp/src/SpacetimeDBClient.cs | 10 ++++- sdks/csharp/src/SpacetimeDBNetworkManager.cs | 43 +++++++++++++++++++ .../src/SpacetimeDBNetworkManager.cs.meta | 11 +++++ 8 files changed, 107 insertions(+), 22 deletions(-) delete mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDBNetworkManager.cs create mode 100644 sdks/csharp/src/SpacetimeDBNetworkManager.cs.meta diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs deleted file mode 100644 index 21ab1ef45b1..00000000000 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/UnityNetworkManager.cs +++ /dev/null @@ -1,21 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.Types -{ - // This class is only used in Unity projects. - // Attach this to a gameobject in your scene to use SpacetimeDB. - #if UNITY_5_3_OR_NEWER - public class UnityNetworkManager : UnityEngine.MonoBehaviour - { - private void OnDestroy() => SpacetimeDBClient.instance.Close(); - private void Update() => SpacetimeDBClient.instance.Update(); - } - #endif -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs.meta new file mode 100644 index 00000000000..95ec13f6db3 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3736538171ef3574f914e9e880b67a03 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs.meta new file mode 100644 index 00000000000..486b1dd8d34 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa7fc0d9632450b47a0d88960f28e66a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs.meta new file mode 100644 index 00000000000..ee9369dd8ce --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d989a072d0ab7664ea89ce118d38d8a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs.meta new file mode 100644 index 00000000000..7b775411211 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a21b01e7a4f857a469aa9181dececc57 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 6aa22f9d867..0df4c7b33c0 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -34,6 +34,9 @@ public DbConnection Build() throw new InvalidOperationException("Building DbConnection with a null nameOrAddress. Call WithModuleName() first."); } conn.Connect(token, uri, nameOrAddress); +#if UNITY_5_3_OR_NEWER + UnityNetworkManager.ActiveConnections.Add(conn); +#endif return conn; } @@ -76,7 +79,9 @@ public DbConnectionBuilder OnDisconnect(Action : IDbConnection @@ -146,6 +151,9 @@ protected DbConnectionBase() webSocket = new WebSocket(options); webSocket.OnMessage += OnMessageReceived; webSocket.OnSendError += a => onSendError?.Invoke(a); +#if UNITY_5_3_OR_NEWER + webSocket.OnClose += (a, b) => UnityNetworkManager.ActiveConnections.Remove(this); +#endif networkMessageProcessThread = new Thread(PreProcessMessages); networkMessageProcessThread.Start(); diff --git a/sdks/csharp/src/SpacetimeDBNetworkManager.cs b/sdks/csharp/src/SpacetimeDBNetworkManager.cs new file mode 100644 index 00000000000..129d87c3968 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDBNetworkManager.cs @@ -0,0 +1,43 @@ +#if UNITY_5_3_OR_NEWER +using System; +using System.Collections.Generic; +using SpacetimeDB; +using UnityEngine; + +namespace SpacetimeDB +{ + // This class is only used in Unity projects. + // Attach this to a gameobject in your scene to use SpacetimeDB. + public class SpacetimeDBNetworkManager : MonoBehaviour + { + private static bool _alreadyInitialized; + + public void Awake() + { + // Ensure that users don't create several UnityNetworkManager instances. + // We're using a global (static) list of active connections and we don't want several instances to walk over it several times. + if (_alreadyInitialized) + { + throw new InvalidOperationException("UnityNetworkManager is a singleton and should only be attached once."); + } + else + { + _alreadyInitialized = true; + } + } + + internal static HashSet ActiveConnections = new(); + + private void ForEachConnection(Action action) + { + foreach (var conn in ActiveConnections) + { + action(conn); + } + } + + private void Update() => ForEachConnection(conn => conn.FrameTick()); + private void OnDestroy() => ForEachConnection(conn => conn.Disconnect()); + } +} +#endif diff --git a/sdks/csharp/src/SpacetimeDBNetworkManager.cs.meta b/sdks/csharp/src/SpacetimeDBNetworkManager.cs.meta new file mode 100644 index 00000000000..e8f74142b1a --- /dev/null +++ b/sdks/csharp/src/SpacetimeDBNetworkManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e016ef92e52934343857fd26e55140c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 072d9ead84df70ba9c037ac44f253f2301bb2ec9 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:39:13 -0500 Subject: [PATCH 130/223] Upgrade SDK Version to 0.12 (#156) ## Description of Changes *Describe what has been changed, any new features or bug fixes* - Upgrade version to 0.12. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* Co-authored-by: John Detter --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 2 +- sdks/csharp/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 006a68bf0aa..eb7773dbb19 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -15,7 +15,7 @@ https://spacetimedb.com logo.png README.md - https://github.com/clockworklabs/spacetimedb-csharp-sdk + https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk 0.12.0 $(AssemblyVersion) $(DefaultItemExcludes);*~/** diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 86f04059235..2bf0c6f8b84 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "0.11.0", + "version": "0.12.0", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From d2143ccc8856f872bb707c0b6c6648cc5b40c1bb Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 3 Oct 2024 20:15:37 -0500 Subject: [PATCH 131/223] Use SpacetimeDBNetworkManager everywhere (#157) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* Co-authored-by: John Detter --- sdks/csharp/README.md | 4 ++-- sdks/csharp/src/SpacetimeDBClient.cs | 4 ++-- sdks/csharp/src/SpacetimeDBNetworkManager.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 18cb6f04172..75c5fba0f55 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -26,9 +26,9 @@ Download the [.unitypackage release](https://github.com/clockworklabs/SpacetimeD ## Usage -### UnityNetworkManager +### SpacetimeDBNetworkManager -The Unity SDK for SpacetimeDB requires that there is a `UnityNetworkManager` component attached to a GameObject in the scene. The `UnityNetworkManager` component is responsible for connecting to SpacetimeDB and managing the connection. The `UnityNetworkManager` component is a singleton and there can only be one instance of it in the scene. +The Unity SDK for SpacetimeDB requires that there is a `SpacetimeDBNetworkManager` component attached to a GameObject in the scene. The `UnityNetworkManager` component is responsible for connecting to SpacetimeDB and managing the connection. The `UnityNetworkManager` component is a singleton and there can only be one instance of it in the scene. ### Connecting to SpacetimeDB diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 0df4c7b33c0..5ba858f9b97 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -35,7 +35,7 @@ public DbConnection Build() } conn.Connect(token, uri, nameOrAddress); #if UNITY_5_3_OR_NEWER - UnityNetworkManager.ActiveConnections.Add(conn); + SpacetimeDBNetworkManager.ActiveConnections.Add(conn); #endif return conn; } @@ -152,7 +152,7 @@ protected DbConnectionBase() webSocket.OnMessage += OnMessageReceived; webSocket.OnSendError += a => onSendError?.Invoke(a); #if UNITY_5_3_OR_NEWER - webSocket.OnClose += (a, b) => UnityNetworkManager.ActiveConnections.Remove(this); + webSocket.OnClose += (a, b) => SpacetimeDBNetworkManager.ActiveConnections.Remove(this); #endif networkMessageProcessThread = new Thread(PreProcessMessages); diff --git a/sdks/csharp/src/SpacetimeDBNetworkManager.cs b/sdks/csharp/src/SpacetimeDBNetworkManager.cs index 129d87c3968..ae5e2d4fb1d 100644 --- a/sdks/csharp/src/SpacetimeDBNetworkManager.cs +++ b/sdks/csharp/src/SpacetimeDBNetworkManager.cs @@ -14,11 +14,11 @@ public class SpacetimeDBNetworkManager : MonoBehaviour public void Awake() { - // Ensure that users don't create several UnityNetworkManager instances. + // Ensure that users don't create several SpacetimeDBNetworkManager instances. // We're using a global (static) list of active connections and we don't want several instances to walk over it several times. if (_alreadyInitialized) { - throw new InvalidOperationException("UnityNetworkManager is a singleton and should only be attached once."); + throw new InvalidOperationException("SpacetimeDBNetworkManager is a singleton and should only be attached once."); } else { From c3be5b08c38287a770fef1c314dabd6048ca9976 Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Fri, 4 Oct 2024 00:12:43 -0400 Subject: [PATCH 132/223] Update to tests/examples follow codegen changes (#160) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --- .../examples~/quickstart/client/Program.cs | 20 +-- .../client/module_bindings/Message.cs | 2 +- .../module_bindings/SendMessageReducer.cs | 2 +- .../client/module_bindings/SetNameReducer.cs | 2 +- .../quickstart/client/module_bindings/User.cs | 2 +- .../_Globals/SpacetimeDBClient.cs | 166 +++++++++--------- .../examples~/quickstart/server/src/lib.rs | 34 ++-- .../SpacetimeDB/ClientApi/DatabaseUpdate.cs | 1 - .../src/SpacetimeDB/ClientApi/EnergyQuanta.cs | 1 - .../SpacetimeDB/ClientApi/IdentityToken.cs | 1 - .../ClientApi/InitialSubscription.cs | 1 - .../src/SpacetimeDB/ClientApi/OneOffTable.cs | 1 - .../src/SpacetimeDB/ClientApi/Subscribe.cs | 1 - .../src/SpacetimeDB/ClientApi/TableUpdate.cs | 1 - .../src/SpacetimeDB/ClientApi/Timestamp.cs | 1 - .../ClientApi/TransactionUpdate.cs | 1 - ...otTests.VerifyAllTablesParsed.verified.txt | 32 ++-- sdks/csharp/tests~/SnapshotTests.cs | 36 ++-- 18 files changed, 150 insertions(+), 155 deletions(-) diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index 29ad6c95c97..8327d9764d5 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -31,13 +31,13 @@ void Main() .OnDisconnect(OnDisconnect) .Build(); - conn.RemoteTables.User.OnInsert += User_OnInsert; - conn.RemoteTables.User.OnUpdate += User_OnUpdate; + conn.Db.User.OnInsert += User_OnInsert; + conn.Db.User.OnUpdate += User_OnUpdate; - conn.RemoteTables.Message.OnInsert += Message_OnInsert; + conn.Db.Message.OnInsert += Message_OnInsert; - conn.RemoteReducers.OnSetName += Reducer_OnSetNameEvent; - conn.RemoteReducers.OnSendMessage += Reducer_OnSendMessageEvent; + conn.Reducers.OnSetName += Reducer_OnSetNameEvent; + conn.Reducers.OnSendMessage += Reducer_OnSendMessageEvent; #pragma warning disable CS0612 // Using obsolete API conn.onUnhandledReducerError += onUnhandledReducerError; @@ -88,7 +88,7 @@ void User_OnUpdate(EventContext ctx, User oldValue, User newValue) void PrintMessage(RemoteTables tables, Message message) { - var sender = tables.User.FindByIdentity(message.Sender); + var sender = tables.User.Identity.Find(message.Sender); var senderName = "unknown"; if (sender != null) { @@ -100,7 +100,7 @@ void PrintMessage(RemoteTables tables, Message message) void Message_OnInsert(EventContext ctx, Message insertedValue) { - if (ctx.Reducer is not Event.SubscribeApplied) + if (ctx.Event is not Event.SubscribeApplied) { PrintMessage(ctx.Db, insertedValue); } @@ -108,7 +108,7 @@ void Message_OnInsert(EventContext ctx, Message insertedValue) void Reducer_OnSetNameEvent(EventContext ctx, string name) { - if (ctx.Reducer is Event.Reducer reducer) + if (ctx.Event is Event.Reducer reducer) { var e = reducer.ReducerEvent; if (e.CallerIdentity == local_identity && e.Status is Status.Failed(var error)) @@ -120,7 +120,7 @@ void Reducer_OnSetNameEvent(EventContext ctx, string name) void Reducer_OnSendMessageEvent(EventContext ctx, string text) { - if (ctx.Reducer is Event.Reducer reducer) + if (ctx.Event is Event.Reducer reducer) { var e = reducer.ReducerEvent; if (e.CallerIdentity == local_identity && e.Status is Status.Failed(var error)) @@ -182,7 +182,7 @@ void ProcessThread(DbConnection conn, CancellationToken ct) { conn.FrameTick(); - ProcessCommands(conn.RemoteReducers); + ProcessCommands(conn.Reducers); Thread.Sleep(100); } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs index c0e52cf0e1a..c63d4bfada5 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.Types @@ -39,5 +38,6 @@ public Message() this.Sender = new(); this.Text = ""; } + } } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs index 45dd29f339e..1510667186a 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs @@ -10,7 +10,7 @@ namespace SpacetimeDB.Types { [SpacetimeDB.Type] - public partial class SendMessageArgsStruct : IReducerArgs + public partial class SendMessage : IReducerArgs { string IReducerArgs.ReducerName => "send_message"; diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs index 0f96ad9e1f6..83a0b7281eb 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs @@ -10,7 +10,7 @@ namespace SpacetimeDB.Types { [SpacetimeDB.Type] - public partial class SetNameArgsStruct : IReducerArgs + public partial class SetName : IReducerArgs { string IReducerArgs.ReducerName => "set_name"; diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs index a6d6d1b9b30..2d4c79b073e 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.Types @@ -38,5 +37,6 @@ public User() { this.Identity = new(); } + } } diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs index cf4f4e95ff7..c0fb266b8c5 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs @@ -5,75 +5,74 @@ #nullable enable using System; -using System.Collections.Generic; - +using SpacetimeDB; using SpacetimeDB.ClientApi; +using System.Collections.Generic; namespace SpacetimeDB.Types { public sealed class RemoteTables { - public class MessageHandle : RemoteTableHandle { - public IEnumerable FilterBySender(SpacetimeDB.Identity value) { - return Query(x => x.Sender == value); - } - - public IEnumerable FilterBySent(ulong value) { - return Query(x => x.Sent == value); - } - - public IEnumerable FilterByText(string value) { - return Query(x => x.Text == value); - } - } - - public class UserHandle : RemoteTableHandle { - public override object? GetPrimaryKey(IDatabaseRow row) => ((User)row).Identity; - - private Dictionary Identity_Index = new(16); - - public override void InternalInvokeValueInserted(IDatabaseRow row) { - var value = (User)row; - Identity_Index[value.Identity] = value; - } - - public override void InternalInvokeValueDeleted(IDatabaseRow row) { - Identity_Index.Remove(((User)row).Identity); - } - - public User? FindByIdentity(SpacetimeDB.Identity value) { - Identity_Index.TryGetValue(value, out var r); - return r; - } - - public IEnumerable FilterByIdentity(SpacetimeDB.Identity value) { - if (FindByIdentity(value) is { } found) { - yield return found; - } - } - - public IEnumerable FilterByOnline(bool value) { - return Query(x => x.Online == value); - } - } - - public readonly MessageHandle Message = new(); + public class MessageHandle : RemoteTableHandle + { + internal MessageHandle() + { + } + + } + + public readonly MessageHandle Message = new(); + + public class UserHandle : RemoteTableHandle + { + private static Dictionary Identity_Index = new(16); + + public override void InternalInvokeValueInserted(IDatabaseRow row) + { + var value = (User)row; + Identity_Index[value.Identity] = value; + } + + public override void InternalInvokeValueDeleted(IDatabaseRow row) + { + Identity_Index.Remove(((User)row).Identity); + } + + public readonly ref struct IdentityUniqueIndex + { + public User? Find(SpacetimeDB.Identity value) + { + Identity_Index.TryGetValue(value, out var r); + return r; + } + + } + + public IdentityUniqueIndex Identity => new(); + + internal UserHandle() + { + } + public override object GetPrimaryKey(IDatabaseRow row) => ((User)row).Identity; + + } + public readonly UserHandle User = new(); + } public sealed class RemoteReducers : RemoteBase { internal RemoteReducers(DbConnection conn) : base(conn) {} - public delegate void SendMessageHandler(EventContext ctx, string text); public event SendMessageHandler? OnSendMessage; public void SendMessage(string text) { - conn.InternalCallReducer(new SendMessageArgsStruct { Text = text }); + conn.InternalCallReducer(new SendMessage { Text = text }); } - public bool InvokeSendMessage(EventContext ctx, SendMessageArgsStruct args) + public bool InvokeSendMessage(EventContext ctx, SendMessage args) { if (OnSendMessage == null) return false; OnSendMessage( @@ -87,10 +86,10 @@ public bool InvokeSendMessage(EventContext ctx, SendMessageArgsStruct args) public void SetName(string name) { - conn.InternalCallReducer(new SetNameArgsStruct { Name = name }); + conn.InternalCallReducer(new SetName { Name = name }); } - public bool InvokeSetName(EventContext ctx, SetNameArgsStruct args) + public bool InvokeSetName(EventContext ctx, SetName args) { if (OnSetName == null) return false; OnSetName( @@ -101,64 +100,69 @@ public bool InvokeSetName(EventContext ctx, SetNameArgsStruct args) } } - public partial record EventContext : DbContext, IEventContext { + public partial record EventContext : DbContext, IEventContext + { public readonly RemoteReducers Reducers; - public readonly Event Reducer; + public readonly Event Event; - internal EventContext(DbConnection conn, Event reducer) : base(conn.RemoteTables) { - Reducers = conn.RemoteReducers; - Reducer = reducer; + internal EventContext(DbConnection conn, Event reducerEvent) : base(conn.Db) + { + Reducers = conn.Reducers; + Event = reducerEvent; } } [Type] public partial record Reducer : TaggedEnum<( - SendMessageArgsStruct SendMessage, - SetNameArgsStruct SetName, - Unit IdentityConnected, - Unit IdentityDisconnected - )>; - + SendMessage SendMessage, + SetName SetName, + Unit StdbNone, + Unit StdbIdentityConnected, + Unit StdbIdentityDisconnected + )>; public class DbConnection : DbConnectionBase { - public readonly RemoteTables RemoteTables = new(); - public readonly RemoteReducers RemoteReducers; + public readonly RemoteTables Db = new(); + public readonly RemoteReducers Reducers; public DbConnection() { - RemoteReducers = new(this); + Reducers = new(this); - clientDB.AddTable("Message", RemoteTables.Message); - clientDB.AddTable("User", RemoteTables.User); + clientDB.AddTable("message", Db.Message); + clientDB.AddTable("user", Db.User); } protected override Reducer ToReducer(TransactionUpdate update) { var encodedArgs = update.ReducerCall.Args; return update.ReducerCall.ReducerName switch { - "send_message" => new Reducer.SendMessage(BSATNHelpers.Decode(encodedArgs)), - "set_name" => new Reducer.SetName(BSATNHelpers.Decode(encodedArgs)), - "__identity_connected__" => new Reducer.IdentityConnected(default), - "__identity_disconnected__" => new Reducer.IdentityDisconnected(default), + "send_message" => new Reducer.SendMessage(BSATNHelpers.Decode(encodedArgs)), + "set_name" => new Reducer.SetName(BSATNHelpers.Decode(encodedArgs)), + "" => new Reducer.StdbNone(default), + "__identity_connected__" => new Reducer.StdbIdentityConnected(default), + "__identity_disconnected__" => new Reducer.StdbIdentityDisconnected(default), + "" => new Reducer.StdbNone(default), var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } - protected override IEventContext ToEventContext(Event reducerEvent) { - return new EventContext(this, reducerEvent); - } + protected override IEventContext ToEventContext(Event reducerEvent) => + new EventContext(this, reducerEvent); - protected override bool Dispatch(IEventContext context, Reducer reducer) { + protected override bool Dispatch(IEventContext context, Reducer reducer) + { var eventContext = (EventContext)context; return reducer switch { - Reducer.SendMessage(var args) => RemoteReducers.InvokeSendMessage(eventContext, args), - Reducer.SetName(var args) => RemoteReducers.InvokeSetName(eventContext, args), - Reducer.IdentityConnected => true, - Reducer.IdentityDisconnected => true, + Reducer.SendMessage(var args) => Reducers.InvokeSendMessage(eventContext, args), + Reducer.SetName(var args) => Reducers.InvokeSetName(eventContext, args), + Reducer.StdbNone or + Reducer.StdbIdentityConnected or + Reducer.StdbIdentityDisconnected => true, _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } - public SubscriptionBuilder SubscriptionBuilder() => new(this); + public SubscriptionBuilder SubscriptionBuilder() => new(this); } } diff --git a/sdks/csharp/examples~/quickstart/server/src/lib.rs b/sdks/csharp/examples~/quickstart/server/src/lib.rs index 0c6572e1975..015aaefeaba 100644 --- a/sdks/csharp/examples~/quickstart/server/src/lib.rs +++ b/sdks/csharp/examples~/quickstart/server/src/lib.rs @@ -1,7 +1,7 @@ -use spacetimedb::{ReducerContext, Identity, Timestamp}; +use spacetimedb::{ReducerContext, Identity, Table, Timestamp}; use anyhow::{Result, anyhow}; -#[spacetimedb::table(name = User, public)] +#[spacetimedb::table(name = user, public)] pub struct User { #[primary_key] identity: Identity, @@ -9,7 +9,7 @@ pub struct User { online: bool, } -#[spacetimedb::table(name = Message, public)] +#[spacetimedb::table(name = message, public)] pub struct Message { sender: Identity, sent: Timestamp, @@ -17,20 +17,20 @@ pub struct Message { } #[spacetimedb::reducer(init)] -pub fn init() { - // Called when the module is initially published +pub fn init(_ctx: &ReducerContext) { + } #[spacetimedb::reducer(client_connected)] -pub fn identity_connected(ctx: ReducerContext) { - if let Some(user) = User::filter_by_identity(&ctx.sender) { +pub fn identity_connected(ctx: &ReducerContext) { + if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { // If this is a returning user, i.e. we already have a `User` with this `Identity`, // set `online: true`, but leave `name` and `identity` unchanged. - User::update_by_identity(&ctx.sender, User { online: true, ..user }); + ctx.db.user().identity().update(User { online: true, ..user }); } else { // If this is a new user, create a `User` row for the `Identity`, // which is online, but hasn't set a name. - User::insert(User { + ctx.db.user().try_insert(User { name: None, identity: ctx.sender, online: true, @@ -39,9 +39,9 @@ pub fn identity_connected(ctx: ReducerContext) { } #[spacetimedb::reducer(client_disconnected)] -pub fn identity_disconnected(ctx: ReducerContext) { - if let Some(user) = User::filter_by_identity(&ctx.sender) { - User::update_by_identity(&ctx.sender, User { online: false, ..user }); +pub fn identity_disconnected(ctx: &ReducerContext) { + if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { + ctx.db.user().identity().update(User { online: false, ..user }); } else { // This branch should be unreachable, // as it doesn't make sense for a client to disconnect without connecting first. @@ -58,10 +58,10 @@ fn validate_name(name: String) -> Result { } #[spacetimedb::reducer] -pub fn set_name(ctx: ReducerContext, name: String) -> Result<()> { +pub fn set_name(ctx: &ReducerContext, name: String) -> Result<()> { let name = validate_name(name)?; - if let Some(user) = User::filter_by_identity(&ctx.sender) { - User::update_by_identity(&ctx.sender, User { name: Some(name), ..user }); + if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { + ctx.db.user().identity().update(User { name: Some(name), ..user }); Ok(()) } else { Err(anyhow!("Cannot set name for unknown user")) @@ -77,12 +77,12 @@ fn validate_message(text: String) -> Result { } #[spacetimedb::reducer] -pub fn send_message(ctx: ReducerContext, text: String) -> Result<()> { +pub fn send_message(ctx: &ReducerContext, text: String) -> Result<()> { // Things to consider: // - Rate-limit messages per-user. // - Reject messages from unnamed users. let text = validate_message(text)?; - Message::insert(Message { + ctx.db.message().insert(Message { sender: ctx.sender, text, sent: ctx.timestamp, diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs index 3294c6b77df..98460753484 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs index 476712e9661..e571a9e1e6b 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs index 4a53ad2fd8a..751fcd75153 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs index cdbc73de2a7..c614410137a 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs index d1f48f3f942..fe667b18ad7 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs index 0adad9b285c..c58f1a46521 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs index cc2586d3ccd..d3265065dcd 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs index c0f53ba1a95..92bd242d50a 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs index e4925bf40e9..d2c349ce8d0 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt index 53528975301..ea57bb0e9b2 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -8,7 +8,7 @@ OnInsertUser: { eventContext: { Reducers: {Scrubbed}, - Reducer: {}, + Event: {}, Db: {Scrubbed} }, user: { @@ -20,7 +20,7 @@ OnInsertUser: { eventContext: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_1, Status: {}, @@ -40,7 +40,7 @@ OnUpdateUser: { eventContext: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_2, Status: {}, @@ -68,7 +68,7 @@ }, OnSetName: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_2, Status: {}, @@ -87,7 +87,7 @@ OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_3, Status: {}, @@ -111,7 +111,7 @@ }, OnSendMessage: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_3, Status: {}, @@ -130,7 +130,7 @@ OnUpdateUser: { eventContext: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_4, Status: {}, @@ -158,7 +158,7 @@ }, OnSetName: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_4, Status: {}, @@ -177,7 +177,7 @@ OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_5, Status: {}, @@ -201,7 +201,7 @@ }, OnSendMessage: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_5, Status: {}, @@ -220,7 +220,7 @@ OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_6, Status: {}, @@ -244,7 +244,7 @@ }, OnSendMessage: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_6, Status: {}, @@ -263,7 +263,7 @@ OnUpdateUser: { eventContext: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_7, Status: {}, @@ -289,7 +289,7 @@ OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_8, Status: {}, @@ -313,7 +313,7 @@ }, OnSendMessage: { Reducers: {Scrubbed}, - Reducer: { + Event: { ReducerEvent: { Timestamp: DateTimeOffset_8, Status: {}, @@ -390,4 +390,4 @@ Max: type=InitialSubscription } } -} +} \ No newline at end of file diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 8e99242e456..d293c126782 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -190,7 +190,7 @@ private static byte[] Encode(in T value) where T : IStructuralReadWrite } private static TableUpdate SampleUserInsert(string identity, string? name, bool online) => - SampleUpdate(4097, "User", [new User + SampleUpdate(4097, "user", [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = name, @@ -198,7 +198,7 @@ private static TableUpdate SampleUserInsert(string identity, string? name, bool }], []); private static TableUpdate SampleUserUpdate(string identity, string? oldName, string? newName, bool oldOnline, bool newOnline) => - SampleUpdate(4097, "User", [new User + SampleUpdate(4097, "user", [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = newName, @@ -211,7 +211,7 @@ private static TableUpdate SampleUserUpdate(string identity, string? oldName, st }]); private static TableUpdate SampleMessage(string identity, ulong sent, string text) => - SampleUpdate(4098, "Message", [new Message + SampleUpdate(4098, "message", [new Message { Sender = Identity.From(Convert.FromBase64String(identity)), Sent = sent, @@ -238,27 +238,27 @@ private static ServerMessage[] SampleDump() => [ SampleTransactionUpdate( 1718487768057579, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", 1, "set_name", 4345615, 70, [SampleUserUpdate("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, "A", true, true)], - Encode(new SetNameArgsStruct { Name = "A" }) + Encode(new SetName { Name = "A" }) ), SampleTransactionUpdate( 1718487775346381, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", 1, "send_message", 2779615, 57, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487775346381, "Hello, A!")], - Encode(new SendMessageArgsStruct { Text = "Hello, A!" }) + Encode(new SendMessage { Text = "Hello, A!" }) ), SampleTransactionUpdate( 1718487777307855, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", 2, "set_name", 4268615, 98, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, "B", true, true)], - Encode(new SetNameArgsStruct { Name = "B" }) + Encode(new SetName { Name = "B" }) ), SampleTransactionUpdate( 1718487783175083, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", 2, "send_message", 2677615, 40, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487783175083, "Hello, B!")], - Encode(new SendMessageArgsStruct { Text = "Hello, B!" }) + Encode(new SendMessage { Text = "Hello, B!" }) ), SampleTransactionUpdate( 1718487787645364, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", 3, "send_message", 2636615, 28, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487787645364, "Goodbye!")], - Encode(new SendMessageArgsStruct { Text = "Goodbye!" }) + Encode(new SendMessage { Text = "Goodbye!" }) ), SampleTransactionUpdate( 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", @@ -268,7 +268,7 @@ private static ServerMessage[] SampleDump() => [ SampleTransactionUpdate( 1718487794937841, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", 3, "send_message", 2636615, 34, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487794937841, "Goodbye!")], - Encode(new SendMessageArgsStruct { Text = "Goodbye!" }) + Encode(new SendMessage { Text = "Goodbye!" }) ), ]; @@ -319,15 +319,15 @@ public async Task VerifyAllTablesParsed() client.onUnhandledReducerError += (exception) => events.Add("OnUnhandledReducerError", exception); #pragma warning restore CS0612 // Using obsolete API - client.RemoteReducers.OnSendMessage += (eventContext, _text) => + client.Reducers.OnSendMessage += (eventContext, _text) => events.Add("OnSendMessage", eventContext); - client.RemoteReducers.OnSetName += (eventContext, _name) => events.Add("OnSetName", eventContext); + client.Reducers.OnSetName += (eventContext, _name) => events.Add("OnSetName", eventContext); - client.RemoteTables.User.OnDelete += (eventContext, user) => + client.Db.User.OnDelete += (eventContext, user) => events.Add("OnDeleteUser", new { eventContext, user }); - client.RemoteTables.User.OnInsert += (eventContext, user) => + client.Db.User.OnInsert += (eventContext, user) => events.Add("OnInsertUser", new { eventContext, user }); - client.RemoteTables.User.OnUpdate += (eventContext, oldUser, newUser) => + client.Db.User.OnUpdate += (eventContext, oldUser, newUser) => events.Add( "OnUpdateUser", new @@ -338,9 +338,9 @@ public async Task VerifyAllTablesParsed() } ); - client.RemoteTables.Message.OnDelete += (eventContext, message) => + client.Db.Message.OnDelete += (eventContext, message) => events.Add("OnDeleteMessage", new { eventContext, message }); - client.RemoteTables.Message.OnInsert += (eventContext, message) => + client.Db.Message.OnInsert += (eventContext, message) => events.Add("OnInsertMessage", new { eventContext, message }); // Simulate receiving WebSocket messages. @@ -362,8 +362,8 @@ await Verify( Events = events, FinalSnapshot = new { - User = client.RemoteTables.User.Iter().ToList(), - Message = client.RemoteTables.Message.Iter().ToList() + User = client.Db.User.Iter().ToList(), + Message = client.Db.Message.Iter().ToList() }, Stats = client.stats } From f376c0543351382a6d6fc489bd0e168914a6894a Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 3 Oct 2024 21:43:39 -0700 Subject: [PATCH 133/223] 0.12.0 DLLs (again) (#161) ## Description of Changes Update with the latest DLLs from the current 0.12.0 branch. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --------- Co-authored-by: Zeke Foppa --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 57856 -> 57856 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 68096 -> 68096 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 222b592781a64e8c004ffecde831368d31b1689e..a17cd51fa7ba5288355b2a1cbfa19eab65a012bf 100644 GIT binary patch delta 238 zcmZoT!rX9#c|r$^yk6ArjXisI2;_z8-cKk^_nB>z7uuimqIz@0&JszDWP>F0M3a)n}+6NcGizDP8sBzgsu*7}jqVy%EahpUhyuki=ll zkjP-dkiwA4V8oEjV8&nxq>X{1ra;jo1`8l74JexeLH=y0AV{@TU)6+(&eLCf%Q-%Mv*?XbHh&`q1BO(F zBnD#!6NY34LmWkLr_TB_}pjXgb21*VIaFn#JW^_)X{1ra;jo1`8l74JexeWkLswq?Jkk#-5(10&KkP6G}b>xlYyIqOj^;r_pAOXSYQ)j0{qfj7^da z4J?z>QY{iKEG44Gc_;6HQVLH*5cS$jmbDM%Kou0*nCyrx$P0 zJHoZrbLqB8lebUhUOKgaaj61SkP{{dRBgB}?#rcoHkPLd zki=ljV8W2hU5ngVqvf>jxA KZ)9VvX9fVXn@pMj From 1e13ab5b50151fcce12884b158253b271b6c7ec5 Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Sat, 12 Oct 2024 10:40:26 -0400 Subject: [PATCH 134/223] Jeremie/one off query decoupled from table (#163) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* --------- Co-authored-by: John Detter --- sdks/csharp/src/ClientCache.cs | 6 ++++++ sdks/csharp/src/SpacetimeDBClient.cs | 25 +++++++++++++++---------- sdks/csharp/src/Table.cs | 15 +++++++++++++++ 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/sdks/csharp/src/ClientCache.cs b/sdks/csharp/src/ClientCache.cs index 0ec8ad911bc..9e01e32741f 100644 --- a/sdks/csharp/src/ClientCache.cs +++ b/sdks/csharp/src/ClientCache.cs @@ -10,8 +10,12 @@ namespace SpacetimeDB // It should just provide auto-generated `GetTable` and `GetTables` methods. public class ClientCache { + private readonly IDbConnection conn; + private readonly Dictionary tables = new(); + public ClientCache(IDbConnection conn) => this.conn = conn; + public void AddTable(string name, IRemoteTableHandle table) where Row : IDatabaseRow, new() { @@ -19,6 +23,8 @@ public void AddTable(string name, IRemoteTableHandle table) { Log.Error($"Table with name already exists: {name}"); } + + table.Initialize(name, conn); } internal IRemoteTableHandle? GetTable(string name) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 5ba858f9b97..dc627f2f6f6 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -82,6 +82,8 @@ public interface IDbConnection internal void Subscribe(ISubscriptionHandle handle, string[] querySqls); void FrameTick(); void Disconnect(); + + internal Task RemoteQuery(string query) where T : IDatabaseRow, new(); } public abstract class DbConnectionBase : IDbConnection @@ -129,7 +131,7 @@ struct DbOp internal WebSocket webSocket; private bool connectionClosed; - protected readonly ClientCache clientDB = new(); + protected readonly ClientCache clientDB; protected abstract Reducer ToReducer(TransactionUpdate update); protected abstract IEventContext ToEventContext(Event reducerEvent); @@ -142,6 +144,8 @@ struct DbOp protected DbConnectionBase() { + clientDB = new(this); + var options = new WebSocket.ConnectOptions { //v1.bin.spacetimedb @@ -830,24 +834,25 @@ void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) )); } - /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("WHERE sender = \"bob\""); - public async Task OneOffQuery(string query) - where T : IDatabaseRow, new() + /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("SELECT * FROM table WHERE sender = \"bob\""); + [Obsolete("This is replaced by ctx.Db.TableName.OneOffQuery(\"WHERE ...\")", false)] + public Task OneOffQuery(string query) where T : IDatabaseRow, new() => + ((IDbConnection)this).RemoteQuery(query); + + async Task IDbConnection.RemoteQuery(string query) { var messageId = Guid.NewGuid(); - var type = typeof(T); var resultSource = new TaskCompletionSource(); waitingOneOffQueries[messageId] = resultSource; // unsanitized here, but writes will be prevented serverside. // the best they can do is send multiple selects, which will just result in them getting no data back. - string queryString = $"SELECT * FROM {type.Name} {query}"; var requestId = stats.OneOffRequestTracker.StartTrackingRequest(); webSocket.Send(new ClientMessage.OneOffQuery(new OneOffQuery { MessageId = messageId.ToByteArray(), - QueryString = queryString, + QueryString = query, })); // Suspend for an arbitrary amount of time @@ -860,7 +865,7 @@ public async Task OneOffQuery(string query) T[] LogAndThrow(string error) { - error = $"While processing one-off-query `{queryString}`, ID {messageId}: {error}"; + error = $"While processing one-off-query `{query}`, ID {messageId}: {error}"; Log.Error(error); throw new Exception(error); } @@ -879,9 +884,9 @@ T[] LogAndThrow(string error) var resultTable = result.Tables[0]; var cacheTable = clientDB.GetTable(resultTable.TableName); - if (cacheTable?.ClientTableType != type) + if (cacheTable?.ClientTableType != typeof(T)) { - return LogAndThrow($"Mismatched result type, expected {type} but got {resultTable.TableName}"); + return LogAndThrow($"Mismatched result type, expected {typeof(T)} but got {resultTable.TableName}"); } return BsatnRowListIter(resultTable.Rows) diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index 2f5f3c6e971..d3ebf918b44 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using SpacetimeDB.BSATN; @@ -36,12 +37,23 @@ public interface IRemoteTableHandle internal void InvokeDelete(IEventContext context, IDatabaseRow row); internal void InvokeBeforeDelete(IEventContext context, IDatabaseRow row); internal void InvokeUpdate(IEventContext context, IDatabaseRow oldRow, IDatabaseRow newRow); + + internal void Initialize(string name, IDbConnection conn); } public abstract class RemoteTableHandle : IRemoteTableHandle where EventContext : class, IEventContext where Row : IDatabaseRow, new() { + string? name; + IDbConnection? conn; + + void IRemoteTableHandle.Initialize(string name, IDbConnection conn) + { + this.name = name; + this.conn = conn; + } + // These methods need to be overridden by autogen. public virtual object? GetPrimaryKey(IDatabaseRow row) => null; public virtual void InternalInvokeValueInserted(IDatabaseRow row) { } @@ -93,6 +105,9 @@ bool IRemoteTableHandle.DeleteEntry(byte[] rowBytes) protected IEnumerable Query(Func filter) => Iter().Where(filter); + public Task RemoteQuery(string query) => + conn!.RemoteQuery($"SELECT * FROM {name!} {query}"); + void IRemoteTableHandle.InvokeInsert(IEventContext context, IDatabaseRow row) => OnInsert?.Invoke((EventContext)context, (Row)row); From 01a7e3f6e980db65326e5dba760ec350e0c141e2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 15 Oct 2024 21:47:40 +0200 Subject: [PATCH 135/223] Add gzip + none compression algos and let SDK pick compression (#155) ## Description of Changes Companion to https://github.com/clockworklabs/SpacetimeDB/pull/1802. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/1802 --- sdks/csharp/src/Compression.cs | 9 ++++ .../ClientApi/CompressableQueryUpdate.cs | 3 +- sdks/csharp/src/SpacetimeDBClient.cs | 48 ++++++++++++------- sdks/csharp/src/WebSocket.cs | 4 +- 4 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 sdks/csharp/src/Compression.cs diff --git a/sdks/csharp/src/Compression.cs b/sdks/csharp/src/Compression.cs new file mode 100644 index 00000000000..8f630f99476 --- /dev/null +++ b/sdks/csharp/src/Compression.cs @@ -0,0 +1,9 @@ +namespace SpacetimeDB +{ + public enum Compression + { + None, + Brotli, + Gzip, + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs index af397a580bd..1af6fd27c4f 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs @@ -12,6 +12,7 @@ namespace SpacetimeDB.ClientApi [SpacetimeDB.Type] public partial record CompressableQueryUpdate : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.QueryUpdate Uncompressed, - byte[] Brotli + byte[] Brotli, + byte[] Gzip )>; } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index dc627f2f6f6..e076fa49e9f 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -22,6 +22,7 @@ public sealed class DbConnectionBuilder string? uri; string? nameOrAddress; string? token; + Compression? compression; public DbConnection Build() { @@ -33,7 +34,7 @@ public DbConnection Build() { throw new InvalidOperationException("Building DbConnection with a null nameOrAddress. Call WithModuleName() first."); } - conn.Connect(token, uri, nameOrAddress); + conn.Connect(token, uri, nameOrAddress, compression ?? Compression.Brotli); #if UNITY_5_3_OR_NEWER SpacetimeDBNetworkManager.ActiveConnections.Add(conn); #endif @@ -58,6 +59,12 @@ public DbConnectionBuilder WithCredentials(in (Identity i return this; } + public DbConnectionBuilder WithCompression(Compression compression) + { + this.compression = compression; + return this; + } + public DbConnectionBuilder OnConnect(Action cb) { conn.onConnect += (identity, token) => cb.Invoke(conn, identity, token); @@ -209,6 +216,17 @@ enum CompressionAlgos : byte { None = 0, Brotli = 1, + Gzip = 2, + } + + private static BinaryReader BrotliReader(Stream stream) + { + return new BinaryReader(new BrotliStream(stream, CompressionMode.Decompress)); + } + + private static BinaryReader GzipReader(Stream stream) + { + return new BinaryReader(new GZipStream(stream, CompressionMode.Decompress)); } private static ServerMessage DecompressDecodeMessage(byte[] bytes) @@ -221,16 +239,11 @@ private static ServerMessage DecompressDecodeMessage(byte[] bytes) switch (compression) { case CompressionAlgos.None: - { - using var binaryReader = new BinaryReader(stream); - return new ServerMessage.BSATN().Read(binaryReader); - } + return new ServerMessage.BSATN().Read(new BinaryReader(stream)); case CompressionAlgos.Brotli: - { - using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); - using var binaryReader = new BinaryReader(decompressedStream); - return new ServerMessage.BSATN().Read(binaryReader); - } + return new ServerMessage.BSATN().Read(BrotliReader(stream)); + case CompressionAlgos.Gzip: + return new ServerMessage.BSATN().Read(GzipReader(stream)); default: throw new InvalidOperationException("Unknown compression type"); } @@ -244,12 +257,11 @@ private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate u return qu; case CompressableQueryUpdate.Brotli(var bytes): - { - using var stream = new MemoryStream(bytes); - using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); - using var binaryReader = new BinaryReader(decompressedStream); - return new QueryUpdate.BSATN().Read(binaryReader); - } + return new QueryUpdate.BSATN().Read(BrotliReader(new MemoryStream(bytes))); + + case CompressableQueryUpdate.Gzip(var bytes): + return new QueryUpdate.BSATN().Read(GzipReader(new MemoryStream(bytes))); + default: throw new InvalidOperationException(); } @@ -579,7 +591,7 @@ public void Disconnect() ///

    /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - internal void Connect(string? token, string uri, string addressOrName) + internal void Connect(string? token, string uri, string addressOrName, Compression compression) { isClosing = false; @@ -597,7 +609,7 @@ internal void Connect(string? token, string uri, string addressOrName) { try { - await webSocket.Connect(token, uri, addressOrName, Address); + await webSocket.Connect(token, uri, addressOrName, Address, compression); } catch (Exception e) { diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index cd22c26feac..dd0dae757d8 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -50,9 +50,9 @@ public WebSocket(ConnectOptions options) public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } - public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress) + public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress, Compression compression) { - var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}"); + var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}&compression={nameof(compression)}"); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000); From 035ee4beb9dc18f33a3e6417ef03083f8991e6ae Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Wed, 16 Oct 2024 00:05:17 -0500 Subject: [PATCH 136/223] Revert PR 155 (#173) ## Description of Changes *Describe what has been changed, any new features or bug fixes* PR 155 introduced a build issue in Unity: ![image](https://github.com/user-attachments/assets/7e88a813-93bd-4b74-ad87-a4c821a7fb98) This PR reverts back to a known working commit. I have tested after reverting the commit and the branch is back to working properly. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* Not breaking ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testing *Write instructions for a test that you performed for this PR* - [x] Tested circle game against this commit and it builds + works Co-authored-by: John Detter --- sdks/csharp/src/Compression.cs | 9 ---- .../ClientApi/CompressableQueryUpdate.cs | 3 +- sdks/csharp/src/SpacetimeDBClient.cs | 48 +++++++------------ sdks/csharp/src/WebSocket.cs | 4 +- 4 files changed, 21 insertions(+), 43 deletions(-) delete mode 100644 sdks/csharp/src/Compression.cs diff --git a/sdks/csharp/src/Compression.cs b/sdks/csharp/src/Compression.cs deleted file mode 100644 index 8f630f99476..00000000000 --- a/sdks/csharp/src/Compression.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace SpacetimeDB -{ - public enum Compression - { - None, - Brotli, - Gzip, - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs index 1af6fd27c4f..af397a580bd 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs @@ -12,7 +12,6 @@ namespace SpacetimeDB.ClientApi [SpacetimeDB.Type] public partial record CompressableQueryUpdate : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.QueryUpdate Uncompressed, - byte[] Brotli, - byte[] Gzip + byte[] Brotli )>; } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index e076fa49e9f..dc627f2f6f6 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -22,7 +22,6 @@ public sealed class DbConnectionBuilder string? uri; string? nameOrAddress; string? token; - Compression? compression; public DbConnection Build() { @@ -34,7 +33,7 @@ public DbConnection Build() { throw new InvalidOperationException("Building DbConnection with a null nameOrAddress. Call WithModuleName() first."); } - conn.Connect(token, uri, nameOrAddress, compression ?? Compression.Brotli); + conn.Connect(token, uri, nameOrAddress); #if UNITY_5_3_OR_NEWER SpacetimeDBNetworkManager.ActiveConnections.Add(conn); #endif @@ -59,12 +58,6 @@ public DbConnectionBuilder WithCredentials(in (Identity i return this; } - public DbConnectionBuilder WithCompression(Compression compression) - { - this.compression = compression; - return this; - } - public DbConnectionBuilder OnConnect(Action cb) { conn.onConnect += (identity, token) => cb.Invoke(conn, identity, token); @@ -216,17 +209,6 @@ enum CompressionAlgos : byte { None = 0, Brotli = 1, - Gzip = 2, - } - - private static BinaryReader BrotliReader(Stream stream) - { - return new BinaryReader(new BrotliStream(stream, CompressionMode.Decompress)); - } - - private static BinaryReader GzipReader(Stream stream) - { - return new BinaryReader(new GZipStream(stream, CompressionMode.Decompress)); } private static ServerMessage DecompressDecodeMessage(byte[] bytes) @@ -239,11 +221,16 @@ private static ServerMessage DecompressDecodeMessage(byte[] bytes) switch (compression) { case CompressionAlgos.None: - return new ServerMessage.BSATN().Read(new BinaryReader(stream)); + { + using var binaryReader = new BinaryReader(stream); + return new ServerMessage.BSATN().Read(binaryReader); + } case CompressionAlgos.Brotli: - return new ServerMessage.BSATN().Read(BrotliReader(stream)); - case CompressionAlgos.Gzip: - return new ServerMessage.BSATN().Read(GzipReader(stream)); + { + using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); + using var binaryReader = new BinaryReader(decompressedStream); + return new ServerMessage.BSATN().Read(binaryReader); + } default: throw new InvalidOperationException("Unknown compression type"); } @@ -257,11 +244,12 @@ private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate u return qu; case CompressableQueryUpdate.Brotli(var bytes): - return new QueryUpdate.BSATN().Read(BrotliReader(new MemoryStream(bytes))); - - case CompressableQueryUpdate.Gzip(var bytes): - return new QueryUpdate.BSATN().Read(GzipReader(new MemoryStream(bytes))); - + { + using var stream = new MemoryStream(bytes); + using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); + using var binaryReader = new BinaryReader(decompressedStream); + return new QueryUpdate.BSATN().Read(binaryReader); + } default: throw new InvalidOperationException(); } @@ -591,7 +579,7 @@ public void Disconnect() ///
    /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - internal void Connect(string? token, string uri, string addressOrName, Compression compression) + internal void Connect(string? token, string uri, string addressOrName) { isClosing = false; @@ -609,7 +597,7 @@ internal void Connect(string? token, string uri, string addressOrName, Compressi { try { - await webSocket.Connect(token, uri, addressOrName, Address, compression); + await webSocket.Connect(token, uri, addressOrName, Address); } catch (Exception e) { diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index dd0dae757d8..cd22c26feac 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -50,9 +50,9 @@ public WebSocket(ConnectOptions options) public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } - public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress, Compression compression) + public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress) { - var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}&compression={nameof(compression)}"); + var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}"); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000); From cf3f37cf77b10371d00ff9dda45143e636270327 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 29 Oct 2024 11:33:15 -0700 Subject: [PATCH 137/223] Update DLLs and bump package versions to `1.0.0-rc1` (#180) ## Description of Changes Update the SpacetimeDB C# DLLs to be up to date with `master` in SpacetimeDB (now that C# bindings have been bumped to `v1.0.0-rc1`). We will need a followup PR ## API Not a breaking change. ## Requires SpacetimeDB PRs `master` ## Testing Only automated tests --------- Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 6 +++--- sdks/csharp/package.json | 2 +- .../SpacetimeDB.BSATN.Runtime.dll | Bin 68096 -> 0 bytes .../{0.12.0.meta => 1.0.0.meta} | 0 .../{0.12.0 => 1.0.0}/analyzers.meta | 0 .../{0.12.0 => 1.0.0}/analyzers/dotnet.meta | 0 .../analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 57856 -> 57344 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{0.12.0 => 1.0.0}/lib.meta | 0 .../{0.12.0 => 1.0.0}/lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 64512 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 13 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0.meta => 1.0.0.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0 => 1.0.0}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0 => 1.0.0}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0 => 1.0.0}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0 => 1.0.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (83%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0 => 1.0.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0 => 1.0.0}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0 => 1.0.0}/lib/netstandard2.1.meta (100%) create mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{0.12.0 => 1.0.0}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index eb7773dbb19..6bf4edcf99d 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,15 +16,15 @@ logo.png README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk - 0.12.0 - $(AssemblyVersion) + 1.0.0 + 1.0.0-rc1 $(DefaultItemExcludes);*~/** packages - + diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 2bf0c6f8b84..015b4e0a2a5 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "0.12.0", + "version": "1.0.0", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll deleted file mode 100644 index 4197c459741c228f3cd90f0f7ec497c9f29e1e59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68096 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

    J$+|aH zt({~Nb`@^s_kUjEJG6ZNRkb!ZrJV(qjV?Ipj^leKZ>eQC zt>Ckqz@ny}RP%WD`y`%N&LLO8yT>O{F5o(YJU@S#`1k*&WzlEx6Quk*Bm9sh?J@e9 zLcs!88+UGIa94;=PWgOx88?jhc~ELC0Lz;_P2l+?7Uxb;(w~ic*X+L99%t8!y9W_RYJE2cHk~t{Bfaxazq`FGumjnCB_( zglBs-aGS(?;Rp@zIU;`_BDn8Iy=_2F^NbkyNwmRd&ga!dk>osTp8y`O(@Fiac#qiX zjK-9-&ZpQedKK0E*18#q=w{?L-6%Z8?}_k!QhLSvlEHY6p$|MWFoMzHm!GqE++&GV z@b0CD{!mL{kN)>^j6kPV{6j3FaNh~N=gmiQrPdnI7kj$`8}LCh4mrko0s^11$a2cy zsd?54?2RRkxw?bhyq#`BnGRv*;O{@6jqr3z*xNhtR`~Ulv95ZzYdEUkhhYO_81+XX z^?tFkaX=2@uQZISeSjVSbO|R-9)-p7l+OWBj{$ZF{|=(O4{*W`;>wdxh$`_nML50_ wuq0Y6Z$tB@avn3BBNvWzRE}Vrso!6H-h&1Z)6?f(4IJ)!VD+o2|Nk`bKZM%;o&W#< diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll similarity index 83% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index a17cd51fa7ba5288355b2a1cbfa19eab65a012bf..bcbcf0ef5a8048fa49abe3ed5f29c7e968896c71 100644 GIT binary patch delta 4417 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 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib/netstandard2.1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/0.12.0/lib/netstandard2.1.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll new file mode 100644 index 0000000000000000000000000000000000000000..329765a8ece422bbc4ae14cf2818ae5e07beb858 GIT binary patch literal 64512 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


    sOnVO^lcRA#6aUS+6CR zKgTXOGZW5sI5gd;&Q>|T6!vD<8l0?ZZS)RRIb_!D%vviMS)5r8sm*%xI-5A@jWJHv zyxmOAba+8z`P2f^Hont;{0ZM_3FZ&K_02c_;PWrG?<|e~V7zDrZO8garOU}-$LakE zK4Vsox4VnY=9x;PWv+3|wi|}_XqxB$;Mb^TrwHS^{?DfLcBI~@G=uF!aFz!*^blTr zr}(>E=2!o)fYGO(#z&f0%rg6#udoYuk<=1zkDevJ#PuX;ecns|^uL_8M$_b=zKua2 zRVf`$eiq5_Ha5>xy42IKyMfwsT<6J+KA*CsR-o#sOAoqs7da0}&V9a<{-GXX)2DdP z_~Dw~u{?9^&bxm{c~XT8%-`@fE5ATVeb@NscGn3M*xlE;fikt~d5?A<)v7oadDphg z-!i8ORv3L5d1zNNqHFJ855Bao8P`~b`#jRpsQ`_wyQ2>6dFt_$_U9YC)f$g-mR(St z1b7@>?X{@wIB)st`#1D07QQK$v=V`?aVN8Jpoj$l2`{>X`~y>e;=MB^yY|m^!e0mU(R{D zq^?qtoRrgio5$$Phsh=G(>!nX253t1R7E`6$JK54Et+Q^Dz{U*v1|`ff0gqFpQg{x z*}p1dTxYEFTx(pPCmr&q=ehInR**u~d Date: Wed, 30 Oct 2024 12:33:54 -0400 Subject: [PATCH 138/223] Fixed subscription updates not clearing tables with no subscribed values (#182) ## Description of Changes *Describe what has been changed, any new features or bug fixes* Context: https://discord.com/channels/568217153853980682/669989878955638785/1301132060878049332 Currently, when we receive subscription updates, a table will only be diffed if subscription has any rows for that table. If, however, there are no subscribed values, that table will NOT be diffed, and therefore will not get cleared. Values from previous subscription will still be there, so the table is in incorrect state. This PR fixes that by making sure that ALL tables are checked in state diff ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testing *Write instructions for a test that you performed for this PR* - [ ] Create a table A with an `val: i32` field - [ ] Generate rows for table A with field values in the range (0..100) - [ ] Connect client and subscribe to `SELECT * FROM A WHERE val > 0` (will have all rows from table A) - [ ] Change your subscription to `SELECT * FROM A WHERE val > 1000` (should have no rows) - [ ] Note that after subscription is applied, table A will have no values Co-authored-by: Steve Boytsun --- sdks/csharp/src/SpacetimeDBClient.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index dc627f2f6f6..ae9476ab232 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -547,7 +547,10 @@ ProcessedMessage CalculateStateDiff(PreProcessedMessage preProcessedMessage) { if (!subscriptionInserts.TryGetValue(table.ClientTableType, out var hashSet)) { - continue; + // We still need to process tables that weren't included in subscription. + // Otherwise we won't delete no-longer-available values + hashSet = new HashSet(); + subscriptionInserts.Add(table.ClientTableType, hashSet); } foreach (var (rowBytes, oldValue) in table.IterEntries().Where(kv => !hashSet.Contains(kv.Key))) From b2c5b4117042a1edcba60fa7c5f871ee81953116 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:08:36 +0000 Subject: [PATCH 139/223] Fix Connection Error: Success (#166) ## Description of Changes This PR edits the handling of errors related to websocket connections and disconnections. In particular, clients and users would often run into the dreaded `Connection Error: Success` message which was confusing and frustrating. This PR better addresses the error by providing more guidance and debug info for the user. It is unfortunately still suboptimal because the `HttpStatusCode` is not available in the .NET core version that Unity supports. We try to be as helpful as possible in this scenario. ## API - [x] This is an API breaking change to the SDK, because it changes the returned values from the `OnDisconnect` and `OnConnectError` callbacks to implement the API specification: https://github.com/clockworklabs/SpacetimeDBPrivate/pull/866/files#diff-be533cc04817c33605a68d717c6ec320c4449904266ee8e1096971e9e17e8d31R424 ## Requires SpacetimeDB PRs No changes to SpacetimeDB required. ## Testing I, Tyler, have tested this and confirmed it to be working with CircleGame. Here is a sample of the output in the case of `Connection Error: Success`: image --------- Co-authored-by: John Detter Co-authored-by: Tyler Cloutier Co-authored-by: Zeke Foppa --- .../examples~/quickstart/client/Program.cs | 4 +- sdks/csharp/src/SpacetimeDBClient.cs | 10 +- sdks/csharp/src/WebSocket.cs | 132 +++++++++++++++--- 3 files changed, 123 insertions(+), 23 deletions(-) diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index 8327d9764d5..f6978ff6a98 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -144,12 +144,12 @@ void OnConnect(DbConnection conn, Identity identity, string authToken) .Subscribe("SELECT * FROM Message"); } -void OnConnectError(WebSocketError? error, string message) +void OnConnectError(Exception e) { } -void OnDisconnect(DbConnection conn, WebSocketCloseStatus? status, WebSocketError? error) +void OnDisconnect(DbConnection conn, Exception? e) { } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index ae9476ab232..40f8d0cc5b0 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -64,15 +64,15 @@ public DbConnectionBuilder OnConnect(Action OnConnectError(Action cb) + public DbConnectionBuilder OnConnectError(Action cb) { - conn.webSocket.OnConnectError += (a, b) => cb.Invoke(a, b); + conn.webSocket.OnConnectError += (e) => cb.Invoke(e); return this; } - public DbConnectionBuilder OnDisconnect(Action cb) + public DbConnectionBuilder OnDisconnect(Action cb) { - conn.webSocket.OnClose += (code, error) => cb.Invoke(conn, code, error); + conn.webSocket.OnClose += (e) => cb.Invoke(conn, e); return this; } } @@ -156,7 +156,7 @@ protected DbConnectionBase() webSocket.OnMessage += OnMessageReceived; webSocket.OnSendError += a => onSendError?.Invoke(a); #if UNITY_5_3_OR_NEWER - webSocket.OnClose += (a, b) => SpacetimeDBNetworkManager.ActiveConnections.Remove(this); + webSocket.OnClose += (e) => SpacetimeDBNetworkManager.ActiveConnections.Remove(this); #endif networkMessageProcessThread = new Thread(PreProcessMessages); diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index cd22c26feac..78247b4498c 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Linq; +using System.Net.Sockets; using System.Net.WebSockets; using System.Text; using System.Threading; @@ -17,9 +18,9 @@ internal class WebSocket public delegate void MessageEventHandler(byte[] message, DateTime timestamp); - public delegate void CloseEventHandler(WebSocketCloseStatus? code, WebSocketError? error); + public delegate void CloseEventHandler(Exception? e); - public delegate void ConnectErrorEventHandler(WebSocketError? error, string message); + public delegate void ConnectErrorEventHandler(Exception e); public delegate void SendErrorEventHandler(Exception e); public struct ConnectOptions @@ -70,23 +71,81 @@ public async Task Connect(string? auth, string host, string nameOrAddress, Addre try { await Ws.ConnectAsync(url, source.Token); - if (OnConnect != null) dispatchQueue.Enqueue(() => OnConnect()); + if (Ws.State == WebSocketState.Open) + { + if (OnConnect != null) + { + dispatchQueue.Enqueue(() => OnConnect()); + } + } + else + { + if (OnConnectError != null) + { + dispatchQueue.Enqueue(() => OnConnectError( + new Exception($"WebSocket connection failed. Current state: {Ws.State}"))); + } + return; + } + } + catch (WebSocketException ex) when (ex.WebSocketErrorCode == WebSocketError.Success) + { + // How can we get here: + // - When you go to connect and the server isn't running (port closed) - target machine actively refused + // - 404 - No module with at that module address instead of 101 upgrade + // - 401? - When the identity received by SpacetimeDB wasn't signed by its signing key + // - 400 - When the auth is malformed + if (OnConnectError != null) + { + // .net 6,7,8 has support for Ws.HttpStatusCode as long as you set + // ClientWebSocketOptions.CollectHttpResponseDetails = true + var message = "A WebSocketException occurred, even though the WebSocketErrorCode is \"Success\".\n" + + "This indicates that there was no native error information for the exception.\n" + + "Due to limitations in the .NET core version we do not have access to the HTTP status code returned by the request which would provide more info on the nature of the error.\n\n" + + "This error could arise for a number of reasons:\n" + + "1. The target machine actively refused the connection.\n" + + "2. The module you are trying to connect to does not exist (404 NOT FOUND).\n" + + "3. The auth token you sent to SpacetimeDB was not signed by the correct signing key (400 BAD REQUEST).\n" + + "4. The auth token is malformed (400 BAD REQUEST).\n" + + "5. You are not authorized (401 UNAUTHORIZED).\n\n" + + "Did you forget to start the server or publish your module?\n\n" + + "Here are some values that might help you debug:\n" + + $"Message: {ex.Message}\n" + + $"WebSocketErrorCode: {ex.WebSocketErrorCode}\n" + + $"ErrorCode: {ex.ErrorCode}\n" + + $"NativeErrorCode: {ex.NativeErrorCode}\n" + + $"InnerException Message: {ex.InnerException?.Message}\n" + + $"WebSocket CloseStatus: {Ws.CloseStatus}\n" + + $"WebSocket State: {Ws.State}\n" + + $"InnerException: {ex.InnerException}\n" + + $"Exception: {ex}" + ; + dispatchQueue.Enqueue(() => OnConnectError(new Exception(message))); + } + } + catch (WebSocketException ex) + { + if (OnConnectError != null) + { + var message = $"WebSocket connection failed: {ex.WebSocketErrorCode}\n" + + $"Exception message: {ex.Message}\n"; + dispatchQueue.Enqueue(() => OnConnectError(new Exception(message))); + } + } + catch (SocketException ex) + { + // This might occur if the server is unreachable or the DNS lookup fails. + if (OnConnectError != null) + { + dispatchQueue.Enqueue(() => OnConnectError(ex)); + } } catch (Exception ex) { - Log.Exception(ex); if (OnConnectError != null) { - var message = ex.Message; - var code = (ex as WebSocketException)?.WebSocketErrorCode; - if (code == WebSocketError.NotAWebSocket) - { - // not a websocket happens when there is no module published under the address specified - message += " Did you forget to publish your module?"; - } - dispatchQueue.Enqueue(() => OnConnectError(code, message)); + dispatchQueue.Enqueue(() => OnConnectError(ex)); } - return; } while (Ws.State == WebSocketState.Open) @@ -102,7 +161,45 @@ public async Task Connect(string? auth, string host, string nameOrAddress, Addre await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } - if (OnClose != null) dispatchQueue.Enqueue(() => OnClose(receiveResult.CloseStatus, null)); + if (OnClose != null) + { + switch (receiveResult.CloseStatus) + { + case WebSocketCloseStatus.NormalClosure: + dispatchQueue.Enqueue(() => OnClose(null)); + break; + case WebSocketCloseStatus.EndpointUnavailable: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1000) The connection has closed after the request was fulfilled."))); + break; + case WebSocketCloseStatus.ProtocolError: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1002) The client or server is terminating the connection because of a protocol error."))); + break; + case WebSocketCloseStatus.InvalidMessageType: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1003) The client or server is terminating the connection because it cannot accept the data type it received."))); + break; + case WebSocketCloseStatus.Empty: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1005) No error specified."))); + break; + case WebSocketCloseStatus.InvalidPayloadData: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1007) The client or server is terminating the connection because it has received data inconsistent with the message type."))); + break; + case WebSocketCloseStatus.PolicyViolation: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1008) The connection will be closed because an endpoint has received a message that violates its policy."))); + break; + case WebSocketCloseStatus.MessageTooBig: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1009) Message too big"))); + break; + case WebSocketCloseStatus.MandatoryExtension: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1010) The client is terminating the connection because it expected the server to negotiate an extension."))); + break; + case WebSocketCloseStatus.InternalServerError: + dispatchQueue.Enqueue(() => OnClose(new Exception("(1011) The connection will be closed by the server because of an error on the server."))); + break; + default: + dispatchQueue.Enqueue(() => OnClose(new Exception("Unknown error"))); + break; + } + } return; } @@ -116,7 +213,10 @@ await Ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, var closeMessage = $"Maximum message size: {MAXMessageSize} bytes."; await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None); - if (OnClose != null) dispatchQueue.Enqueue(() => OnClose(WebSocketCloseStatus.MessageTooBig, null)); + if (OnClose != null) + { + dispatchQueue.Enqueue(() => OnClose(new Exception("(1009) Message too big"))); + } return; } @@ -134,7 +234,7 @@ await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, } catch (WebSocketException ex) { - if (OnClose != null) dispatchQueue.Enqueue(() => OnClose(null, ex.WebSocketErrorCode)); + if (OnClose != null) dispatchQueue.Enqueue(() => OnClose(ex)); return; } } From b728e63158de344d2539d478d4d64f86499fcdc4 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:25:28 +0000 Subject: [PATCH 140/223] Unity testsuite as a git submodule (#186) **Please do not rebase this PR** ## Description of Changes *Describe what has been changed, any new features or bug fixes* This is very similar to https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/176 except it imports the circle game as a submodule instead of copying the code over into this repo. This is the SpacetimeDBCircleGame PR that we're dependent on right now: https://github.com/clockworklabs/SpacetimeDBCircleGame/pull/3 - This PR introduces a testsuite which runs in Unity. Right now it just spawns in a circle, eats some food and verifies the decay logic is working correctly. I've also written some reconnection tests but they don't work because reconnections are currently broken. There are also one-off tests but those don't work either because they also require reconnections to be working. Update: reconnections have been fixed via https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/168. I've used the built-in unity testsuite framework to achieve this, along with the UnityCI tool from GameCI. The documentation for this docker container can be found here: https://game.ci/docs/github/getting-started/ ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* Not breaking ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* None ## Testsuite SpacetimeDB branch name: 0935b7346b825b8cbb9f36d9ed256136b73b5f0b ## Testing *Write instructions for a test that you performed for this PR* - [x] The testsuite is passing: https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/actions/runs/11604456943/job/32313229775 You can follow test instructions here to double check my work: https://github.com/clockworklabs/SpacetimeDBCircleGame/pull/3 ## Follow-up Actions - [ ] Rebase the reconnection logic PR onto this PR and re-enable the reconnection tests --------- Co-authored-by: John Detter --- sdks/csharp/.github/pull_request_template.md | 11 +- sdks/csharp/.github/workflows/unity-test.yml | 149 ++++++++++++++++++ .../workflows/unity-testsuite-bindings.yml | 120 ++++++++++++++ sdks/csharp/.gitmodules | 3 + sdks/csharp/unity-tests~ | 1 + 5 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 sdks/csharp/.github/workflows/unity-test.yml create mode 100644 sdks/csharp/.github/workflows/unity-testsuite-bindings.yml create mode 100644 sdks/csharp/.gitmodules create mode 160000 sdks/csharp/unity-tests~ diff --git a/sdks/csharp/.github/pull_request_template.md b/sdks/csharp/.github/pull_request_template.md index 88fcaef9487..71d6531af42 100644 --- a/sdks/csharp/.github/pull_request_template.md +++ b/sdks/csharp/.github/pull_request_template.md @@ -7,6 +7,15 @@ *If the API is breaking, please state below what will break* - ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* + +## Testsuite +*If you would like to run against a specific SpacetimeDB branch in the testsuite, specify that here. This can be a branch name or a link to a PR.* + +SpacetimeDB branch name: master + +## Testing +*Write instructions for a test that you performed for this PR* + +- [ ] Describe a test for this PR that you have completed diff --git a/sdks/csharp/.github/workflows/unity-test.yml b/sdks/csharp/.github/workflows/unity-test.yml new file mode 100644 index 00000000000..774fd847b2d --- /dev/null +++ b/sdks/csharp/.github/workflows/unity-test.yml @@ -0,0 +1,149 @@ +name: Unity Test Suite + +on: + push: + branches: + - staging + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Checkout submodule + run: | + git submodule init + git submodule update + cd unity-tests~ + git checkout jdetter/circle-game-testsuite + # Grab the branch name from the PR description. If it's not found, master will be used instead. + - name: Extract SpacetimeDB branch name or PR link from PR description + id: extract-branch + if: github.event_name == 'pull_request' + run: | + description=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + ${{ github.event.pull_request.url }} | jq -r '.body') + + # Check if description contains a branch name or a PR link + branch_or_pr=$(echo "$description" | grep -oP '(?<=SpacetimeDB branch name:\s).+') + echo "Branch or PR found: $branch_or_pr" + + if [[ -z "$branch_or_pr" ]]; then + branch="master" + elif [[ "$branch_or_pr" =~ ^https://github.com/.*/pull/[0-9]+$ ]]; then + # If it's a PR link, extract the branch name from the PR + pr_number=$(echo "$branch_or_pr" | grep -oP '[0-9]+$') + branch=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + https://api.github.com/repos/clockworklabs/SpacetimeDB/pulls/$pr_number | jq -r '.head.ref') + else + # It's already a branch name + branch="$branch_or_pr" + fi + + echo "branch=$branch" >> $GITHUB_OUTPUT + echo "Final branch name: $branch" + + - name: Replace com.clockworklabs.spacetimedbsdk in manifest.json + run: | + # Get the branch name from the environment variable + branch_name="${{ github.head_ref }}" + # Replace any reference to com.clockworklabs.spacetimedbsdk with the correct GitHub URL using the current branch + sed -i "s|\"com.clockworklabs.spacetimedbsdk\":.*|\"com.clockworklabs.spacetimedbsdk\": \"https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk.git#$branch_name\",|" unity-tests~/client/Packages/manifest.json + + cat unity-tests~/client/Packages/manifest.json + - name: Replace spacetimedb dependency in Cargo.toml + run: | + # Get the branch name from the environment variable + branch_name="${{ github.head_ref }}" + # Make sure we're using the correct bindings when building the module TODO + sed -i "s|spacetimedb.*=.*|spacetimedb = \{ path = \"../SpacetimeDB/crates/bindings\" \}|" unity-tests~/server/Cargo.toml + cat unity-tests~/server/Cargo.toml + - name: Install Rust toolchain + run: | + curl https://sh.rustup.rs -sSf | sh -s -- -y + source $HOME/.cargo/env + rustup install stable + rustup default stable + + - name: Cache Cargo target directory + uses: actions/cache@v3 + with: + path: unity-tests~/server/target + key: server-target-SpacetimeDBUnityTestsuite-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} + restore-keys: | + server-target-SpacetimeDBUnityTestsuite-${{ runner.os }}-${{ runner.arch }}- + server-target-SpacetimeDBUnityTestsuite- + + - name: Cache Cargo registry + uses: actions/cache@v3 + with: + path: ~/.cargo/registry + key: cargo-registry-${{ runner.os }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} + restore-keys: | + cargo-registry-${{ runner.os }}- + cargo-registry- + + - name: Cache Cargo index + uses: actions/cache@v3 + with: + path: ~/.cargo/git + key: cargo-index-${{ runner.os }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} + restore-keys: | + cargo-index-${{ runner.os }}- + cargo-index- + + - name: Install SpacetimeDB CLI from specific branch + run: | + cd unity-tests~ + git clone https://github.com/clockworklabs/SpacetimeDB.git + cd SpacetimeDB + # Sanitize the branch name by trimming any newlines or spaces + branch_name=$(echo "${{ steps.extract-branch.outputs.branch }}" | tr -d '[:space:]') + # If the branch name is not found, default to master + if [ -z "$branch_name" ]; then + branch_name="master" + fi + git checkout "$branch_name" + echo "Checked out branch: $branch_name" + cargo build --release -p spacetimedb-cli + sudo mv target/release/spacetime /usr/bin/spacetime + + - name: Generate client bindings + run: | + cd unity-tests~/server + bash ./generate.sh -y + + - name: Start SpacetimeDB + run: | + spacetime start & + disown + + - name: Publish module to SpacetimeDB + run: | + cd unity-tests~/server + bash ./publish.sh + + - uses: actions/cache@v3 + with: + path: unity-tests~/client/Library + key: Library-SpacetimeDBUnityTestsuite-Linux-x86 + restore-keys: | + Library-SpacetimeDBUnityTestsuite- + Library- + + - name: Set up Unity + uses: game-ci/unity-test-runner@v4 + with: + unityVersion: 2022.3.32f1 # Adjust Unity version to a valid tag + projectPath: unity-tests~/client # Path to the Unity project subdirectory + githubToken: ${{ secrets.GITHUB_TOKEN }} + testMode: playmode + useHostNetwork: true + env: + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} + diff --git a/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml b/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml new file mode 100644 index 00000000000..1bfee47dfdd --- /dev/null +++ b/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml @@ -0,0 +1,120 @@ +name: Check Unity Testsuite Bindings + +on: + push: + branches: + - staging + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Checkout submodule + run: | + git submodule init + git submodule update + cd unity-tests~ + git checkout jdetter/circle-game-testsuite + # Grab the branch name from the PR description. If it's not found, master will be used instead. + - name: Extract SpacetimeDB branch name or PR link from PR description + id: extract-branch + if: github.event_name == 'pull_request' + run: | + description=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + ${{ github.event.pull_request.url }} | jq -r '.body') + + # Check if description contains a branch name or a PR link + branch_or_pr=$(echo "$description" | grep -oP '(?<=SpacetimeDB branch name:\s).+') + echo "Branch or PR found: $branch_or_pr" + + if [[ -z "$branch_or_pr" ]]; then + branch="master" + elif [[ "$branch_or_pr" =~ ^https://github.com/.*/pull/[0-9]+$ ]]; then + # If it's a PR link, extract the branch name from the PR + pr_number=$(echo "$branch_or_pr" | grep -oP '[0-9]+$') + branch=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + https://api.github.com/repos/clockworklabs/SpacetimeDB/pulls/$pr_number | jq -r '.head.ref') + else + # It's already a branch name + branch="$branch_or_pr" + fi + + echo "branch=$branch" >> $GITHUB_OUTPUT + echo "Final branch name: $branch" + + - name: Replace spacetimedb dependency in Cargo.toml + run: | + # Get the branch name from the environment variable + branch_name="${{ github.head_ref }}" + # Make sure we're using the correct bindings when building the module TODO + sed -i "s|spacetimedb.*=.*|spacetimedb = \{ path = \"../SpacetimeDB/crates/bindings\" \}|" unity-tests~/server/Cargo.toml + cat unity-tests~/server/Cargo.toml + - name: Install Rust toolchain + run: | + curl https://sh.rustup.rs -sSf | sh -s -- -y + source $HOME/.cargo/env + rustup install stable + rustup default stable + + - name: Cache Cargo target directory + uses: actions/cache@v3 + with: + path: unity-tests~/server/target + key: server-target-SpacetimeDBUnityTestsuite-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} + restore-keys: | + server-target-SpacetimeDBUnityTestsuite-${{ runner.os }}-${{ runner.arch }}- + server-target-SpacetimeDBUnityTestsuite- + + - name: Cache Cargo registry + uses: actions/cache@v3 + with: + path: ~/.cargo/registry + key: cargo-registry-${{ runner.os }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} + restore-keys: | + cargo-registry-${{ runner.os }}- + cargo-registry- + + - name: Cache Cargo index + uses: actions/cache@v3 + with: + path: ~/.cargo/git + key: cargo-index-${{ runner.os }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} + restore-keys: | + cargo-index-${{ runner.os }}- + cargo-index- + + - name: Install SpacetimeDB CLI from specific branch + run: | + cd unity-tests~ + git clone https://github.com/clockworklabs/SpacetimeDB.git + cd SpacetimeDB + # Sanitize the branch name by trimming any newlines or spaces + branch_name=$(echo "${{ steps.extract-branch.outputs.branch }}" | tr -d '[:space:]') + # If the branch name is not found, default to master + if [ -z "$branch_name" ]; then + branch_name="master" + fi + git checkout "$branch_name" + echo "Checked out branch: $branch_name" + cargo build --release -p spacetimedb-cli + sudo mv target/release/spacetime /usr/bin/spacetime + + - name: Generate client bindings + run: | + cd unity-tests~/server + bash ./generate.sh -y + + - name: Check for changes + run: | + git diff --exit-code + continue-on-error: true + + - name: Fail if there are changes + if: ${{ steps.check-for-changes.outcome == 'failure' }} + run: | + echo "Error: Bindings are dirty. Please generate bindings again and commit them to this branch." + exit 1 diff --git a/sdks/csharp/.gitmodules b/sdks/csharp/.gitmodules new file mode 100644 index 00000000000..50c54dcb4b7 --- /dev/null +++ b/sdks/csharp/.gitmodules @@ -0,0 +1,3 @@ +[submodule "SpacetimeDBCircleGame"] + path = unity-tests~ + url = https://github.com/clockworklabs/SpacetimeDBCircleGame diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ new file mode 160000 index 00000000000..75047b5e58a --- /dev/null +++ b/sdks/csharp/unity-tests~ @@ -0,0 +1 @@ +Subproject commit 75047b5e58a67ba8e3b652dab17ddde61b661989 From ac45eacf37e3cca56ee2a1fe0b8ed5f37de51c35 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 31 Oct 2024 19:08:52 +0100 Subject: [PATCH 141/223] Add gzip + none compression algos and let SDK pick compression (take 2) (#174) ## Description of Changes Companion to https://github.com/clockworklabs/SpacetimeDB/pull/1802. ## Requires SpacetimeDB PRs None ## Test suite SpacetimeDB branch name: 0935b7346b825b8cbb9f36d9ed256136b73b5f0b --------- Co-authored-by: Jeremie Pelletier Co-authored-by: Zeke Foppa --- sdks/csharp/src/Compression.cs | 9 ++++ sdks/csharp/src/Compression.cs.meta | 11 +++++ .../ClientApi/CompressableQueryUpdate.cs | 3 +- sdks/csharp/src/SpacetimeDBClient.cs | 48 ++++++++++++------- sdks/csharp/src/WebSocket.cs | 4 +- 5 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 sdks/csharp/src/Compression.cs create mode 100644 sdks/csharp/src/Compression.cs.meta diff --git a/sdks/csharp/src/Compression.cs b/sdks/csharp/src/Compression.cs new file mode 100644 index 00000000000..8f630f99476 --- /dev/null +++ b/sdks/csharp/src/Compression.cs @@ -0,0 +1,9 @@ +namespace SpacetimeDB +{ + public enum Compression + { + None, + Brotli, + Gzip, + } +} diff --git a/sdks/csharp/src/Compression.cs.meta b/sdks/csharp/src/Compression.cs.meta new file mode 100644 index 00000000000..eef0325ca41 --- /dev/null +++ b/sdks/csharp/src/Compression.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 03fdc211a87474eeba9f03495eab491e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs index af397a580bd..1af6fd27c4f 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs @@ -12,6 +12,7 @@ namespace SpacetimeDB.ClientApi [SpacetimeDB.Type] public partial record CompressableQueryUpdate : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.QueryUpdate Uncompressed, - byte[] Brotli + byte[] Brotli, + byte[] Gzip )>; } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 40f8d0cc5b0..7fa8dd6f254 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -22,6 +22,7 @@ public sealed class DbConnectionBuilder string? uri; string? nameOrAddress; string? token; + Compression? compression; public DbConnection Build() { @@ -33,7 +34,7 @@ public DbConnection Build() { throw new InvalidOperationException("Building DbConnection with a null nameOrAddress. Call WithModuleName() first."); } - conn.Connect(token, uri, nameOrAddress); + conn.Connect(token, uri, nameOrAddress, compression ?? Compression.Brotli); #if UNITY_5_3_OR_NEWER SpacetimeDBNetworkManager.ActiveConnections.Add(conn); #endif @@ -58,6 +59,12 @@ public DbConnectionBuilder WithCredentials(in (Identity i return this; } + public DbConnectionBuilder WithCompression(Compression compression) + { + this.compression = compression; + return this; + } + public DbConnectionBuilder OnConnect(Action cb) { conn.onConnect += (identity, token) => cb.Invoke(conn, identity, token); @@ -209,6 +216,17 @@ enum CompressionAlgos : byte { None = 0, Brotli = 1, + Gzip = 2, + } + + private static BinaryReader BrotliReader(Stream stream) + { + return new BinaryReader(new BrotliStream(stream, CompressionMode.Decompress)); + } + + private static BinaryReader GzipReader(Stream stream) + { + return new BinaryReader(new GZipStream(stream, CompressionMode.Decompress)); } private static ServerMessage DecompressDecodeMessage(byte[] bytes) @@ -221,16 +239,11 @@ private static ServerMessage DecompressDecodeMessage(byte[] bytes) switch (compression) { case CompressionAlgos.None: - { - using var binaryReader = new BinaryReader(stream); - return new ServerMessage.BSATN().Read(binaryReader); - } + return new ServerMessage.BSATN().Read(new BinaryReader(stream)); case CompressionAlgos.Brotli: - { - using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); - using var binaryReader = new BinaryReader(decompressedStream); - return new ServerMessage.BSATN().Read(binaryReader); - } + return new ServerMessage.BSATN().Read(BrotliReader(stream)); + case CompressionAlgos.Gzip: + return new ServerMessage.BSATN().Read(GzipReader(stream)); default: throw new InvalidOperationException("Unknown compression type"); } @@ -244,12 +257,11 @@ private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate u return qu; case CompressableQueryUpdate.Brotli(var bytes): - { - using var stream = new MemoryStream(bytes); - using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); - using var binaryReader = new BinaryReader(decompressedStream); - return new QueryUpdate.BSATN().Read(binaryReader); - } + return new QueryUpdate.BSATN().Read(BrotliReader(new MemoryStream(bytes))); + + case CompressableQueryUpdate.Gzip(var bytes): + return new QueryUpdate.BSATN().Read(GzipReader(new MemoryStream(bytes))); + default: throw new InvalidOperationException(); } @@ -582,7 +594,7 @@ public void Disconnect() /// /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - internal void Connect(string? token, string uri, string addressOrName) + internal void Connect(string? token, string uri, string addressOrName, Compression compression) { isClosing = false; @@ -600,7 +612,7 @@ internal void Connect(string? token, string uri, string addressOrName) { try { - await webSocket.Connect(token, uri, addressOrName, Address); + await webSocket.Connect(token, uri, addressOrName, Address, compression); } catch (Exception e) { diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 78247b4498c..86f47c70023 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -51,9 +51,9 @@ public WebSocket(ConnectOptions options) public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } - public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress) + public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress, Compression compression) { - var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}"); + var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}&compression={compression}"); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000); From f936c98b04de0c7e776fe4f969a7d7ff14c77ffd Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 31 Oct 2024 22:34:26 +0000 Subject: [PATCH 142/223] Fix Reconnection Logic (#168) ## Description of Changes *Describe what has been changed, any new features or bug fixes* - switched our "already connected" logic to using a reference to a `MonoBehaviour` instead of just a bool. `MonoBehaviour`s are typically destroyed when a scene reload happens and in this case we'll want to allow developers to spawn a new `SpacetimeDBNetworkManager` if the previous one has been destroyed. ## API This is *not* an API break. - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* - https://github.com/clockworklabs/SpacetimeDB/pull/1869 ## Testsuite SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] I have added in several new tests here, one of which is a reconnection test. Also, the reason why we couldn't have more than 1 test before this is that it was required for reconnections to be working in order to have multiple tests running in the testsuite. Now that we have fixed reconnections I have enabled all of the tests. Testsuite passes ![image](https://github.com/user-attachments/assets/09ef5835-f2c7-41f1-af6b-e612ac5e0497) --------- Co-authored-by: John Detter Co-authored-by: Mazdak Farrokhzad Co-authored-by: Jeremie Pelletier Co-authored-by: Zeke Foppa --- sdks/csharp/.github/workflows/unity-test.yml | 2 +- .../workflows/unity-testsuite-bindings.yml | 4 +- sdks/csharp/.gitignore | 1 + sdks/csharp/src/SpacetimeDBClient.cs | 13 +++- sdks/csharp/src/SpacetimeDBNetworkManager.cs | 76 ++++++++++++------- sdks/csharp/unity-tests~ | 2 +- 6 files changed, 63 insertions(+), 35 deletions(-) diff --git a/sdks/csharp/.github/workflows/unity-test.yml b/sdks/csharp/.github/workflows/unity-test.yml index 774fd847b2d..29e508867c9 100644 --- a/sdks/csharp/.github/workflows/unity-test.yml +++ b/sdks/csharp/.github/workflows/unity-test.yml @@ -7,7 +7,7 @@ on: pull_request: jobs: - test: + unity-testsuite: runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml b/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml index 1bfee47dfdd..442abcd1f91 100644 --- a/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml +++ b/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml @@ -7,7 +7,7 @@ on: pull_request: jobs: - test: + check-testsuite-bindings: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -110,7 +110,7 @@ jobs: - name: Check for changes run: | - git diff --exit-code + git diff --exit-code unity-tests~/client/Assets/Scripts/autogen continue-on-error: true - name: Fail if there are changes diff --git a/sdks/csharp/.gitignore b/sdks/csharp/.gitignore index 825b31b18e0..42502a20a58 100644 --- a/sdks/csharp/.gitignore +++ b/sdks/csharp/.gitignore @@ -75,3 +75,4 @@ obj~ # This is used for local paths to SpacetimeDB packages. /nuget.config /nuget.config.meta +.idea/ diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 7fa8dd6f254..d908763c1db 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -36,7 +36,10 @@ public DbConnection Build() } conn.Connect(token, uri, nameOrAddress, compression ?? Compression.Brotli); #if UNITY_5_3_OR_NEWER - SpacetimeDBNetworkManager.ActiveConnections.Add(conn); + if (SpacetimeDBNetworkManager._instance != null) + { + SpacetimeDBNetworkManager._instance.AddConnection(conn); + } #endif return conn; } @@ -163,7 +166,13 @@ protected DbConnectionBase() webSocket.OnMessage += OnMessageReceived; webSocket.OnSendError += a => onSendError?.Invoke(a); #if UNITY_5_3_OR_NEWER - webSocket.OnClose += (e) => SpacetimeDBNetworkManager.ActiveConnections.Remove(this); + webSocket.OnClose += (e) => + { + if (SpacetimeDBNetworkManager._instance != null) + { + SpacetimeDBNetworkManager._instance.RemoveConnection(this); + } + }; #endif networkMessageProcessThread = new Thread(PreProcessMessages); diff --git a/sdks/csharp/src/SpacetimeDBNetworkManager.cs b/sdks/csharp/src/SpacetimeDBNetworkManager.cs index ae5e2d4fb1d..379bf63d86b 100644 --- a/sdks/csharp/src/SpacetimeDBNetworkManager.cs +++ b/sdks/csharp/src/SpacetimeDBNetworkManager.cs @@ -6,38 +6,56 @@ namespace SpacetimeDB { - // This class is only used in Unity projects. - // Attach this to a gameobject in your scene to use SpacetimeDB. - public class SpacetimeDBNetworkManager : MonoBehaviour - { - private static bool _alreadyInitialized; + // This class is only used in Unity projects. + // Attach this to a GameObject in your scene to use SpacetimeDB. + public class SpacetimeDBNetworkManager : MonoBehaviour + { + internal static SpacetimeDBNetworkManager? _instance; - public void Awake() - { - // Ensure that users don't create several SpacetimeDBNetworkManager instances. - // We're using a global (static) list of active connections and we don't want several instances to walk over it several times. - if (_alreadyInitialized) - { - throw new InvalidOperationException("SpacetimeDBNetworkManager is a singleton and should only be attached once."); - } - else - { - _alreadyInitialized = true; - } - } + public void Awake() + { + // Ensure that users don't create several SpacetimeDBNetworkManager instances. + // We're using a global (static) list of active connections and we don't want several instances to walk over it several times. + if (_instance != null) + { + throw new InvalidOperationException("SpacetimeDBNetworkManager is a singleton and should only be attached once."); + } + else + { + _instance = this; + } + } - internal static HashSet ActiveConnections = new(); + private readonly List activeConnections = new(); - private void ForEachConnection(Action action) - { - foreach (var conn in ActiveConnections) - { - action(conn); - } - } + public bool AddConnection(IDbConnection conn) + { + if (activeConnections.Contains(conn)) + { + return false; + } + activeConnections.Add(conn); + return true; - private void Update() => ForEachConnection(conn => conn.FrameTick()); - private void OnDestroy() => ForEachConnection(conn => conn.Disconnect()); - } + } + + public bool RemoveConnection(IDbConnection conn) + { + return activeConnections.Remove(conn); + } + + private void ForEachConnection(Action action) + { + // It's common to call disconnect from Update, which will then modify the ActiveConnections collection, + // therefore we must reverse-iterate the list of connections. + for (var x = activeConnections.Count - 1; x >= 0; x--) + { + action(activeConnections[x]); + } + } + + private void Update() => ForEachConnection(conn => conn.FrameTick()); + private void OnDestroy() => ForEachConnection(conn => conn.Disconnect()); + } } #endif diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index 75047b5e58a..386db35877c 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit 75047b5e58a67ba8e3b652dab17ddde61b661989 +Subproject commit 386db35877caa84a6d8842cde1e8d1a823c7fd78 From 2ad31d65b464e3f3f6bb8f36c9de818afddf353a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 4 Nov 2024 17:46:42 +0100 Subject: [PATCH 143/223] Companion to SpacetimeDB#1812 (light tx, C#) (#170) ## Description of Changes Adds C# sdk support for https://github.com/clockworklabs/SpacetimeDB/pull/1812. ## Requires SpacetimeDB PRs - https://github.com/clockworklabs/SpacetimeDB/pull/1812 ## Testsuite SpacetimeDB branch name: centril/websocket-light --------- Co-authored-by: Tyler Cloutier Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> --- .../_Globals/SpacetimeDBClient.cs | 28 +- sdks/csharp/src/CallReducerFlags.cs | 9 + sdks/csharp/src/CallReducerFlags.cs.meta | 11 + sdks/csharp/src/Compression.cs.meta | 8 +- .../src/SpacetimeDB/ClientApi/BsatnRowList.cs | 1 - .../src/SpacetimeDB/ClientApi/CallReducer.cs | 7 +- .../src/SpacetimeDB/ClientApi/OneOffQuery.cs | 1 - .../ClientApi/OneOffQueryResponse.cs | 1 - .../src/SpacetimeDB/ClientApi/QueryUpdate.cs | 1 - .../SpacetimeDB/ClientApi/ReducerCallInfo.cs | 1 - .../SpacetimeDB/ClientApi/ServerMessage.cs | 1 + .../ClientApi/TransactionUpdateLight.cs | 38 ++ .../ClientApi/TransactionUpdateLight.cs.meta | 11 + sdks/csharp/src/SpacetimeDBClient.cs | 330 ++++++++++-------- sdks/csharp/src/WebSocket.cs | 9 +- ...otTests.VerifyAllTablesParsed.verified.txt | 17 +- sdks/csharp/tools~/gen-client-api.sh | 0 17 files changed, 311 insertions(+), 163 deletions(-) create mode 100644 sdks/csharp/src/CallReducerFlags.cs create mode 100644 sdks/csharp/src/CallReducerFlags.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs.meta mode change 100644 => 100755 sdks/csharp/tools~/gen-client-api.sh diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs index c0fb266b8c5..726f56d0af0 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs @@ -63,13 +63,14 @@ internal UserHandle() public sealed class RemoteReducers : RemoteBase { - internal RemoteReducers(DbConnection conn) : base(conn) {} + internal RemoteReducers(DbConnection conn, SetReducerFlags SetReducerFlags) : base(conn) { this.SetCallReducerFlags = SetReducerFlags; } + internal readonly SetReducerFlags SetCallReducerFlags; public delegate void SendMessageHandler(EventContext ctx, string text); public event SendMessageHandler? OnSendMessage; public void SendMessage(string text) { - conn.InternalCallReducer(new SendMessage { Text = text }); + conn.InternalCallReducer(new SendMessage { Text = text }, this.SetCallReducerFlags.SendMessageFlags); } public bool InvokeSendMessage(EventContext ctx, SendMessage args) @@ -86,7 +87,7 @@ public bool InvokeSendMessage(EventContext ctx, SendMessage args) public void SetName(string name) { - conn.InternalCallReducer(new SetName { Name = name }); + conn.InternalCallReducer(new SetName { Name = name }, this.SetCallReducerFlags.SetNameFlags); } public bool InvokeSetName(EventContext ctx, SetName args) @@ -100,14 +101,25 @@ public bool InvokeSetName(EventContext ctx, SetName args) } } + public sealed class SetReducerFlags + { + internal SetReducerFlags() { } + internal CallReducerFlags SendMessageFlags; + public void SendMessage(CallReducerFlags flags) { this.SendMessageFlags = flags; } + internal CallReducerFlags SetNameFlags; + public void SetName(CallReducerFlags flags) { this.SetNameFlags = flags; } + } + public partial record EventContext : DbContext, IEventContext { public readonly RemoteReducers Reducers; + public readonly SetReducerFlags SetReducerFlags; public readonly Event Event; internal EventContext(DbConnection conn, Event reducerEvent) : base(conn.Db) { Reducers = conn.Reducers; + SetReducerFlags = conn.SetReducerFlags; Event = reducerEvent; } } @@ -124,10 +136,12 @@ public class DbConnection : DbConnectionBase { public readonly RemoteTables Db = new(); public readonly RemoteReducers Reducers; + public readonly SetReducerFlags SetReducerFlags; public DbConnection() { - Reducers = new(this); + SetReducerFlags = new(); + Reducers = new(this, this.SetReducerFlags); clientDB.AddTable("message", Db.Message); clientDB.AddTable("user", Db.User); @@ -136,7 +150,8 @@ public DbConnection() protected override Reducer ToReducer(TransactionUpdate update) { var encodedArgs = update.ReducerCall.Args; - return update.ReducerCall.ReducerName switch { + return update.ReducerCall.ReducerName switch + { "send_message" => new Reducer.SendMessage(BSATNHelpers.Decode(encodedArgs)), "set_name" => new Reducer.SetName(BSATNHelpers.Decode(encodedArgs)), "" => new Reducer.StdbNone(default), @@ -153,7 +168,8 @@ protected override IEventContext ToEventContext(Event reducerEvent) => protected override bool Dispatch(IEventContext context, Reducer reducer) { var eventContext = (EventContext)context; - return reducer switch { + return reducer switch + { Reducer.SendMessage(var args) => Reducers.InvokeSendMessage(eventContext, args), Reducer.SetName(var args) => Reducers.InvokeSetName(eventContext, args), Reducer.StdbNone or diff --git a/sdks/csharp/src/CallReducerFlags.cs b/sdks/csharp/src/CallReducerFlags.cs new file mode 100644 index 00000000000..0a3ea363ef7 --- /dev/null +++ b/sdks/csharp/src/CallReducerFlags.cs @@ -0,0 +1,9 @@ +namespace SpacetimeDB +{ + public enum CallReducerFlags : byte + { + // This is the default. + FullUpdate = 0, + NoSuccessNotify = 1, + } +} diff --git a/sdks/csharp/src/CallReducerFlags.cs.meta b/sdks/csharp/src/CallReducerFlags.cs.meta new file mode 100644 index 00000000000..dbfee1f8689 --- /dev/null +++ b/sdks/csharp/src/CallReducerFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0567f0d188b749659b7291c277a2b17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/Compression.cs.meta b/sdks/csharp/src/Compression.cs.meta index eef0325ca41..31f1b1906b2 100644 --- a/sdks/csharp/src/Compression.cs.meta +++ b/sdks/csharp/src/Compression.cs.meta @@ -1,11 +1,11 @@ fileFormatVersion: 2 -guid: 03fdc211a87474eeba9f03495eab491e +guid: 78dd2c1276a6e4e859d2c4fad671c2c7 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs index 5df43d6bc96..1f17c790676 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs index 7c3ce90eaec..212d9bb352d 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi @@ -22,16 +21,20 @@ public partial class CallReducer public byte[] Args; [DataMember(Name = "request_id")] public uint RequestId; + [DataMember(Name = "flags")] + public byte Flags; public CallReducer( string Reducer, byte[] Args, - uint RequestId + uint RequestId, + byte Flags ) { this.Reducer = Reducer; this.Args = Args; this.RequestId = RequestId; + this.Flags = Flags; } public CallReducer() diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs index 5ee2c66dc8e..11370a540d7 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs index f539516f6ed..2bdb8e1ad0c 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs index 858dea65244..25acc28e7f8 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs index 0ca52252667..f8acaffd411 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs @@ -7,7 +7,6 @@ using System; using SpacetimeDB; using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; namespace SpacetimeDB.ClientApi diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs index 46b5be3adb7..f66fdd98347 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs @@ -13,6 +13,7 @@ namespace SpacetimeDB.ClientApi public partial record ServerMessage : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.InitialSubscription InitialSubscription, SpacetimeDB.ClientApi.TransactionUpdate TransactionUpdate, + SpacetimeDB.ClientApi.TransactionUpdateLight TransactionUpdateLight, SpacetimeDB.ClientApi.IdentityToken IdentityToken, SpacetimeDB.ClientApi.OneOffQueryResponse OneOffQueryResponse )>; diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs new file mode 100644 index 00000000000..3a3ea6b586f --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs @@ -0,0 +1,38 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class TransactionUpdateLight + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "update")] + public SpacetimeDB.ClientApi.DatabaseUpdate Update; + + public TransactionUpdateLight( + uint RequestId, + SpacetimeDB.ClientApi.DatabaseUpdate Update + ) + { + this.RequestId = RequestId; + this.Update = Update; + } + + public TransactionUpdateLight() + { + this.Update = new(); + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs.meta new file mode 100644 index 00000000000..50cff86d4e2 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de607af1bdc1244f894fb952d4199473 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index d908763c1db..c9d7d7041af 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -23,6 +23,7 @@ public sealed class DbConnectionBuilder string? nameOrAddress; string? token; Compression? compression; + bool light; public DbConnection Build() { @@ -34,7 +35,7 @@ public DbConnection Build() { throw new InvalidOperationException("Building DbConnection with a null nameOrAddress. Call WithModuleName() first."); } - conn.Connect(token, uri, nameOrAddress, compression ?? Compression.Brotli); + conn.Connect(token, uri, nameOrAddress, compression ?? Compression.Brotli, light); #if UNITY_5_3_OR_NEWER if (SpacetimeDBNetworkManager._instance != null) { @@ -68,6 +69,12 @@ public DbConnectionBuilder WithCompression(Compression co return this; } + public DbConnectionBuilder WithLightMode(bool light) + { + this.light = light; + return this; + } + public DbConnectionBuilder OnConnect(Action cb) { conn.onConnect += (identity, token) => cb.Invoke(conn, identity, token); @@ -340,18 +347,28 @@ void PreProcessMessages() } } - PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) + IEnumerable<(IRemoteTableHandle, TableUpdate)> GetTables(DatabaseUpdate updates) { - var dbOps = new List(); + foreach (var update in updates.Tables) + { + var tableName = update.TableName; + var table = clientDB.GetTable(tableName); + if (table == null) + { + Log.Error($"Unknown table name: {tableName}"); + continue; + } - var message = DecompressDecodeMessage(unprocessed.bytes); + yield return (table, update); + } + } - ReducerEvent? reducerEvent = default; + (List, Dictionary>?) PreProcessInitialSubscription(InitialSubscription initSub) + { + var dbOps = new List(); // This is all of the inserts Dictionary>? subscriptionInserts = null; - // All row updates that have a primary key, this contains inserts, deletes and updates - var primaryKeyChanges = new Dictionary<(System.Type tableType, object primaryKeyValue), DbOp>(); HashSet GetInsertHashSet(System.Type tableType, int tableSize) { @@ -364,54 +381,168 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) return hashSet; } - switch (message) + int cap = initSub.DatabaseUpdate.Tables.Sum(a => (int)a.NumRows); + subscriptionInserts = new(capacity: cap); + + // First apply all of the state + foreach (var (table, update) in GetTables(initSub.DatabaseUpdate)) { - case ServerMessage.InitialSubscription(var initialSubscription): - int cap = initialSubscription.DatabaseUpdate.Tables.Sum(a => (int)a.NumRows); - subscriptionInserts = new(capacity: cap); + var hashSet = GetInsertHashSet(table.ClientTableType, (int)update.NumRows); + + foreach (var cqu in update.Updates) + { + var qu = DecompressDecodeQueryUpdate(cqu); + if (BsatnRowListCount(qu.Deletes) != 0) + { + Log.Warn("Non-insert during a subscription update!"); + } - // First apply all of the state - foreach (var update in initialSubscription.DatabaseUpdate.Tables) + foreach (var bin in BsatnRowListIter(qu.Inserts)) { - var tableName = update.TableName; - var table = clientDB.GetTable(tableName); - if (table == null) + if (!hashSet.Add(bin)) { - Log.Error($"Unknown table name: {tableName}"); + // Ignore duplicate inserts in the same subscription update. continue; } - var hashSet = GetInsertHashSet(table.ClientTableType, (int)update.NumRows); + var obj = table.DecodeValue(bin); + var op = new DbOp + { + table = table, + insert = new(obj, bin), + }; + + dbOps.Add(op); + } + } + } + + return (dbOps, subscriptionInserts); + } + + List PreProcessDatabaseUpdate(DatabaseUpdate updates) + { + var dbOps = new List(); - foreach (var cqu in update.Updates) + // All row updates that have a primary key, this contains inserts, deletes and updates + var primaryKeyChanges = new Dictionary<(System.Type tableType, object primaryKeyValue), DbOp>(); + + // First apply all of the state + foreach (var (table, update) in GetTables(updates)) + { + foreach (var cqu in update.Updates) + { + var qu = DecompressDecodeQueryUpdate(cqu); + foreach (var row in BsatnRowListIter(qu.Inserts)) + { + var op = new DbOp { table = table, insert = Decode(table, row, out var pk) }; + if (pk != null) { - var qu = DecompressDecodeQueryUpdate(cqu); - if (BsatnRowListCount(qu.Deletes) != 0) + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, pk); + + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { - Log.Warn("Non-insert during a subscription update!"); + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) + { + Log.Warn($"Update with the same primary key was applied multiple times! tableName={update.TableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. + continue; + } + + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + op = new DbOp + { + table = insertOp.table, + delete = deleteOp.delete, + insert = insertOp.insert, + }; } + primaryKeyChanges[key] = op; + } + else + { + dbOps.Add(op); + } + } - foreach (var bin in BsatnRowListIter(qu.Inserts)) + foreach (var row in BsatnRowListIter(qu.Deletes)) + { + var op = new DbOp { table = table, delete = Decode(table, row, out var pk) }; + if (pk != null) + { + // Compound key that we use for lookup. + // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. + var key = (table.ClientTableType, pk); + + if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { - if (!hashSet.Add(bin)) + if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { - // Ignore duplicate inserts in the same subscription update. + Log.Warn($"Update with the same primary key was applied multiple times! tableName={update.TableName}"); + // TODO(jdetter): Is this a correctable error? This would be a major error on the + // SpacetimeDB side. continue; } - var obj = table.DecodeValue(bin); - var op = new DbOp + var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); + op = new DbOp { - table = table, - insert = new(obj, bin), + table = insertOp.table, + delete = deleteOp.delete, + insert = insertOp.insert, }; - - dbOps.Add(op); } + primaryKeyChanges[key] = op; + } + else + { + dbOps.Add(op); } } - break; + } + } + + // Combine primary key updates and non-primary key updates + dbOps.AddRange(primaryKeyChanges.Values); + + return dbOps; + } + + void PreProcessOneOffQuery(OneOffQueryResponse resp) + { + /// This case does NOT produce a list of DBOps, because it should not modify the client cache state! + var messageId = new Guid(resp.MessageId); + if (!waitingOneOffQueries.Remove(messageId, out var resultSource)) + { + Log.Error($"Response to unknown one-off-query: {messageId}"); + return; + } + + resultSource.SetResult(resp); + } + + PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) + { + var dbOps = new List(); + + var message = DecompressDecodeMessage(unprocessed.bytes); + + ReducerEvent? reducerEvent = default; + + // This is all of the inserts + Dictionary>? subscriptionInserts = null; + + switch (message) + { + case ServerMessage.InitialSubscription(var initSub): + var (ops, subIns) = PreProcessInitialSubscription(initSub); + dbOps = ops; + subscriptionInserts = subIns; + break; case ServerMessage.TransactionUpdate(var transactionUpdate): // Convert the generic event arguments in to a domain specific event object try @@ -437,111 +568,16 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) if (transactionUpdate.Status is UpdateStatus.Committed(var committed)) { - primaryKeyChanges = new(); - - // First apply all of the state - foreach (var update in committed.Tables) - { - var tableName = update.TableName; - var table = clientDB.GetTable(tableName); - if (table == null) - { - Log.Error($"Unknown table name: {tableName}"); - continue; - } - - foreach (var cqu in update.Updates) - { - var qu = DecompressDecodeQueryUpdate(cqu); - foreach (var row in BsatnRowListIter(qu.Inserts)) - { - var op = new DbOp { table = table, insert = Decode(table, row, out var pk) }; - if (pk != null) - { - // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, pk); - - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) - { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) - { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; - } - - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - op = new DbOp - { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; - } - primaryKeyChanges[key] = op; - } - else - { - dbOps.Add(op); - } - } - - foreach (var row in BsatnRowListIter(qu.Deletes)) - { - var op = new DbOp { table = table, delete = Decode(table, row, out var pk) }; - if (pk != null) - { - // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, pk); - - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) - { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) - { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={tableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; - } - - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - op = new DbOp - { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; - } - primaryKeyChanges[key] = op; - } - else - { - dbOps.Add(op); - } - } - } - } - - // Combine primary key updates and non-primary key updates - dbOps.AddRange(primaryKeyChanges.Values); + dbOps = PreProcessDatabaseUpdate(committed); } break; + case ServerMessage.TransactionUpdateLight(var update): + dbOps = PreProcessDatabaseUpdate(update.Update); + break; case ServerMessage.IdentityToken(var identityToken): break; case ServerMessage.OneOffQueryResponse(var resp): - /// This case does NOT produce a list of DBOps, because it should not modify the client cache state! - var messageId = new Guid(resp.MessageId); - - if (!waitingOneOffQueries.Remove(messageId, out var resultSource)) - { - Log.Error($"Response to unknown one-off-query: {messageId}"); - break; - } - - resultSource.SetResult(resp); + PreProcessOneOffQuery(resp); break; default: throw new InvalidOperationException(); @@ -603,7 +639,7 @@ public void Disconnect() /// /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - internal void Connect(string? token, string uri, string addressOrName, Compression compression) + internal void Connect(string? token, string uri, string addressOrName, Compression compression, bool light) { isClosing = false; @@ -621,7 +657,7 @@ internal void Connect(string? token, string uri, string addressOrName, Compressi { try { - await webSocket.Connect(token, uri, addressOrName, Address, compression); + await webSocket.Connect(token, uri, addressOrName, Address, compression, light); } catch (Exception e) { @@ -745,6 +781,16 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } break; } + case ServerMessage.TransactionUpdateLight(var update): + { + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdateLight)}"); + + var eventContext = ToEventContext(new Event.UnknownTransaction()); + OnMessageProcessCompleteUpdate(eventContext, dbOps); + + break; + } + case ServerMessage.TransactionUpdate(var transactionUpdate): { var reducer = transactionUpdate.ReducerCall.ReducerName; @@ -820,7 +866,7 @@ internal void OnMessageReceived(byte[] bytes, DateTime timestamp) => _messageQueue.Add(new UnprocessedMessage { bytes = bytes, timestamp = timestamp }); // TODO: this should become [Obsolete] but for now is used by autogenerated code. - public void InternalCallReducer(T args) + public void InternalCallReducer(T args, CallReducerFlags flags) where T : IReducerArgs, new() { if (!webSocket.IsConnected) @@ -829,14 +875,12 @@ public void InternalCallReducer(T args) return; } - webSocket.Send(new ClientMessage.CallReducer( - new CallReducer - { - RequestId = stats.ReducerRequestTracker.StartTrackingRequest(args.ReducerName), - Reducer = args.ReducerName, - Args = IStructuralReadWrite.ToBytes(args) - } - )); + webSocket.Send(new ClientMessage.CallReducer(new CallReducer( + args.ReducerName, + IStructuralReadWrite.ToBytes(args), + stats.ReducerRequestTracker.StartTrackingRequest(args.ReducerName), + (byte)flags + ))); } void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 86f47c70023..bf65c84eed4 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -51,9 +51,14 @@ public WebSocket(ConnectOptions options) public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } - public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress, Compression compression) + public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress, Compression compression, bool light) { - var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}&compression={compression}"); + var uri = $"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}&compression={compression}"; + if (light) + { + uri += "&light=true"; + } + var url = new Uri(uri); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000); diff --git a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt index ea57bb0e9b2..e3ae0cdc908 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -8,6 +8,7 @@ OnInsertUser: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: {}, Db: {Scrubbed} }, @@ -20,6 +21,7 @@ OnInsertUser: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_1, @@ -40,6 +42,7 @@ OnUpdateUser: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_2, @@ -68,6 +71,7 @@ }, OnSetName: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_2, @@ -87,6 +91,7 @@ OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_3, @@ -111,6 +116,7 @@ }, OnSendMessage: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_3, @@ -130,6 +136,7 @@ OnUpdateUser: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_4, @@ -158,6 +165,7 @@ }, OnSetName: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_4, @@ -177,6 +185,7 @@ OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_5, @@ -201,6 +210,7 @@ }, OnSendMessage: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_5, @@ -220,6 +230,7 @@ OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_6, @@ -244,6 +255,7 @@ }, OnSendMessage: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_6, @@ -263,6 +275,7 @@ OnUpdateUser: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_7, @@ -289,6 +302,7 @@ OnInsertMessage: { eventContext: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_8, @@ -313,6 +327,7 @@ }, OnSendMessage: { Reducers: {Scrubbed}, + SetReducerFlags: {}, Event: { ReducerEvent: { Timestamp: DateTimeOffset_8, @@ -390,4 +405,4 @@ Max: type=InitialSubscription } } -} \ No newline at end of file +} diff --git a/sdks/csharp/tools~/gen-client-api.sh b/sdks/csharp/tools~/gen-client-api.sh old mode 100644 new mode 100755 From 181aff332350707fb837a11363e1853276811254 Mon Sep 17 00:00:00 2001 From: Jeremie Pelletier Date: Mon, 4 Nov 2024 14:17:05 -0500 Subject: [PATCH 144/223] Update the quickstart module (#185) ## Description of Changes Fix the quickstart client program, also removes the rust server program (it lives in the stdb main repo under modules/quickstart-chat) ## Testing Second subscription resets the first one without the fix ## Testsuite SpacetimeDB branch name: master --- .../examples~/quickstart/client/Program.cs | 6 +- .../quickstart/server/.cargo/config.toml | 2 - .../examples~/quickstart/server/.gitignore | 13 - .../examples~/quickstart/server/Cargo.lock | 539 ------------------ .../examples~/quickstart/server/Cargo.toml | 14 - .../examples~/quickstart/server/src/lib.rs | 91 --- 6 files changed, 1 insertion(+), 664 deletions(-) delete mode 100644 sdks/csharp/examples~/quickstart/server/.cargo/config.toml delete mode 100644 sdks/csharp/examples~/quickstart/server/.gitignore delete mode 100644 sdks/csharp/examples~/quickstart/server/Cargo.lock delete mode 100644 sdks/csharp/examples~/quickstart/server/Cargo.toml delete mode 100644 sdks/csharp/examples~/quickstart/server/src/lib.rs diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index f6978ff6a98..e8e3bcd96a1 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -137,11 +137,7 @@ void OnConnect(DbConnection conn, Identity identity, string authToken) conn.SubscriptionBuilder() .OnApplied(OnSubscriptionApplied) - .Subscribe("SELECT * FROM User"); - - conn.SubscriptionBuilder() - .OnApplied(OnSubscriptionApplied) - .Subscribe("SELECT * FROM Message"); + .Subscribe("SELECT * FROM user", "SELECT * FROM message"); } void OnConnectError(Exception e) diff --git a/sdks/csharp/examples~/quickstart/server/.cargo/config.toml b/sdks/csharp/examples~/quickstart/server/.cargo/config.toml deleted file mode 100644 index f4e8c002fc2..00000000000 --- a/sdks/csharp/examples~/quickstart/server/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" diff --git a/sdks/csharp/examples~/quickstart/server/.gitignore b/sdks/csharp/examples~/quickstart/server/.gitignore deleted file mode 100644 index 91ad25847ba..00000000000 --- a/sdks/csharp/examples~/quickstart/server/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Cargo -# will have compiled files and executables -debug/ -target/ - -# These are backup files generated by rustfmt -**/*.rs.bk - -# MSVC Windows builds of rustc generate these, which store debugging information -*.pdb - -# Spacetime ignore -/.spacetime diff --git a/sdks/csharp/examples~/quickstart/server/Cargo.lock b/sdks/csharp/examples~/quickstart/server/Cargo.lock deleted file mode 100644 index 372fb071956..00000000000 --- a/sdks/csharp/examples~/quickstart/server/Cargo.lock +++ /dev/null @@ -1,539 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - -[[package]] -name = "anyhow" -version = "1.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" - -[[package]] -name = "approx" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "decorum" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "281759d3c8a14f5c3f0c49363be56810fcd7f910422f97f2db850c2920fde5cf" -dependencies = [ - "approx", - "num-traits", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" - -[[package]] -name = "enum-as-inner" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.32", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "log" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "second-stack" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4904c83c6e51f1b9b08bfa5a86f35a51798e8307186e6f5513852210a219c0bb" - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest", - "keccak", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "spacetime-module" -version = "0.1.0" -dependencies = [ - "anyhow", - "log", - "spacetimedb", -] - -[[package]] -name = "spacetimedb" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec3fbc884bd532f1f9cddcde961686284091dfa3facd49b71c553df28d30a5f" -dependencies = [ - "derive_more", - "getrandom", - "log", - "rand", - "scoped-tls", - "spacetimedb-bindings-macro", - "spacetimedb-bindings-sys", - "spacetimedb-lib", - "spacetimedb-primitives", -] - -[[package]] -name = "spacetimedb-bindings-macro" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a5a6d8be2a892ae1d1175b228f12deffb685947cc30d60449dba98219cc3bc2" -dependencies = [ - "bitflags", - "humantime", - "proc-macro2", - "quote", - "spacetimedb-primitives", - "syn 2.0.32", -] - -[[package]] -name = "spacetimedb-bindings-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a450cdc41a3d6a6a33ba113255c2a1d73dbf32bcf7aa2d272beb58cc6efe9655" -dependencies = [ - "spacetimedb-primitives", -] - -[[package]] -name = "spacetimedb-data-structures" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d866aa0c287936e13f03206f32c15ce46893076918b7d1d9e1a1421ddca2e6a" -dependencies = [ - "hashbrown", - "nohash-hasher", - "thiserror", -] - -[[package]] -name = "spacetimedb-lib" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c1d4c3106bdfe395c8f266df1daff9e6259322bd70d05e3f78c7fa67efd14f" -dependencies = [ - "anyhow", - "bitflags", - "derive_more", - "enum-as-inner", - "hex", - "itertools", - "spacetimedb-bindings-macro", - "spacetimedb-primitives", - "spacetimedb-sats", - "thiserror", -] - -[[package]] -name = "spacetimedb-primitives" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f80f43ce78747ae4deb061130fcbedf9c57cbe9d3db8269e2ce403d6cf3a0c" -dependencies = [ - "bitflags", - "either", - "nohash-hasher", -] - -[[package]] -name = "spacetimedb-sats" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab8da7807277abaef5452d25c3cbc01978297a37d0f00071e52621e655b3a84" -dependencies = [ - "arrayvec", - "bitflags", - "decorum", - "derive_more", - "enum-as-inner", - "hex", - "itertools", - "second-stack", - "sha3", - "smallvec", - "spacetimedb-bindings-macro", - "spacetimedb-data-structures", - "spacetimedb-primitives", - "thiserror", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.32", -] - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "unicode-ident" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "zerocopy" -version = "0.7.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.32", -] diff --git a/sdks/csharp/examples~/quickstart/server/Cargo.toml b/sdks/csharp/examples~/quickstart/server/Cargo.toml deleted file mode 100644 index 735a5ad6c8c..00000000000 --- a/sdks/csharp/examples~/quickstart/server/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "spacetime-module" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -crate-type = ["cdylib"] - -[dependencies] -spacetimedb = "0.10" -log = "0.4" -anyhow = "1.0" diff --git a/sdks/csharp/examples~/quickstart/server/src/lib.rs b/sdks/csharp/examples~/quickstart/server/src/lib.rs deleted file mode 100644 index 015aaefeaba..00000000000 --- a/sdks/csharp/examples~/quickstart/server/src/lib.rs +++ /dev/null @@ -1,91 +0,0 @@ -use spacetimedb::{ReducerContext, Identity, Table, Timestamp}; -use anyhow::{Result, anyhow}; - -#[spacetimedb::table(name = user, public)] -pub struct User { - #[primary_key] - identity: Identity, - name: Option, - online: bool, -} - -#[spacetimedb::table(name = message, public)] -pub struct Message { - sender: Identity, - sent: Timestamp, - text: String, -} - -#[spacetimedb::reducer(init)] -pub fn init(_ctx: &ReducerContext) { - -} - -#[spacetimedb::reducer(client_connected)] -pub fn identity_connected(ctx: &ReducerContext) { - if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { - // If this is a returning user, i.e. we already have a `User` with this `Identity`, - // set `online: true`, but leave `name` and `identity` unchanged. - ctx.db.user().identity().update(User { online: true, ..user }); - } else { - // If this is a new user, create a `User` row for the `Identity`, - // which is online, but hasn't set a name. - ctx.db.user().try_insert(User { - name: None, - identity: ctx.sender, - online: true, - }).unwrap(); - } -} - -#[spacetimedb::reducer(client_disconnected)] -pub fn identity_disconnected(ctx: &ReducerContext) { - if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { - ctx.db.user().identity().update(User { online: false, ..user }); - } else { - // This branch should be unreachable, - // as it doesn't make sense for a client to disconnect without connecting first. - log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender); - } -} - -fn validate_name(name: String) -> Result { - if name.is_empty() { - Err(anyhow!("Names must not be empty")) - } else { - Ok(name) - } -} - -#[spacetimedb::reducer] -pub fn set_name(ctx: &ReducerContext, name: String) -> Result<()> { - let name = validate_name(name)?; - if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { - ctx.db.user().identity().update(User { name: Some(name), ..user }); - Ok(()) - } else { - Err(anyhow!("Cannot set name for unknown user")) - } -} - -fn validate_message(text: String) -> Result { - if text.is_empty() { - Err(anyhow!("Messages must not be empty")) - } else { - Ok(text) - } -} - -#[spacetimedb::reducer] -pub fn send_message(ctx: &ReducerContext, text: String) -> Result<()> { - // Things to consider: - // - Rate-limit messages per-user. - // - Reject messages from unnamed users. - let text = validate_message(text)?; - ctx.db.message().insert(Message { - sender: ctx.sender, - text, - sent: ctx.timestamp, - }); - Ok(()) -} From 82f4b07b90c26565dc69dddd039ee8cbd7e47a71 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:29:48 -0800 Subject: [PATCH 145/223] Bump Unity SDK version to RC1 (#187) ## Description of Changes Just bump `package.json` to `1.0.0-rc1` instead of `1.0.0`. ## API No breaking changes ## Requires SpacetimeDB PRs None ## Testing Co-authored-by: Zeke Foppa --- sdks/csharp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 015b4e0a2a5..7a1c5a6e998 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.0.0", + "version": "1.0.0-rc1", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From 3054a7f530756540a9b4cf7c595328fca1000478 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 19 Nov 2024 13:18:44 -0800 Subject: [PATCH 146/223] Bump version and update DLLs (#192) ## Description of Changes Cherrypicking the changes from https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/190, which were merged directly to `master` (by me, without thinking it through). ## API Fixes API breakage related to endianness. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/1964 ## Testsuite SpacetimeDB branch name: master ## Testing CI only. These changes have already been released. --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- .../{1.0.0.meta => 1.0.0-rc1-hotfix1.meta} | 0 .../analyzers.meta | 0 .../analyzers/dotnet.meta | 0 .../analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 57344 -> 57344 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.0.0 => 1.0.0-rc1-hotfix1}/lib.meta | 0 .../lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 66048 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 64512 -> 0 bytes 12 files changed, 2 insertions(+), 2 deletions(-) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0.meta => 1.0.0-rc1-hotfix1.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.0-rc1-hotfix1}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.0-rc1-hotfix1}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.0-rc1-hotfix1}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.0-rc1-hotfix1}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (91%) mode change 100644 => 100755 rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.0-rc1-hotfix1}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.0-rc1-hotfix1}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.0-rc1-hotfix1}/lib/netstandard2.1.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.0-rc1-hotfix1}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) delete mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 6bf4edcf99d..ddd2f9b3328 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -17,14 +17,14 @@ README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk 1.0.0 - 1.0.0-rc1 + 1.0.0-rc1-hotfix1 $(DefaultItemExcludes);*~/** packages - + diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll old mode 100644 new mode 100755 similarity index 91% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index bcbcf0ef5a8048fa49abe3ed5f29c7e968896c71..d90254a8922ee67bae5352ecc9ae8118877da17e GIT binary patch delta 1730 zcmXw)e{2(F7{{Nt*SWbLIM!~rUR&1fHs&0Ib)#&ffpxaYT$He62pL4v?%G?o2@@fP zAZA^PK;kqk4>87pcBw-!#(O<}L_0<5uusD)aK0?PqJ`{}a95k*WJV_OOjIqYaDL6? z3X}P0S4pL&3)xK z@uqW`tM|DImM5qxEOH*jl7u@>#Uj^QEeJjMUrgQeuTy8z#hD;wYF$A~8g4p+%zG@d ze;;dPMP)aGlAB!yXATgrvM1miavEf}8}WO;yz5oax@P z#i=NADvu(ktyW}zT}guJ(wTQL2@;{%n1qxm%Je8TuttllC{INl9CkyI^B9yrg5E*B z_a(A~1Y9NJG!@BqggTosJ!|v)r z$!iO1AnXnl%FbO(LQKL;B21!8#@SD^zRx7fnRzCQL`K{>CbyW}mISX4cW;vq>tO+Iw_9^MHWUpJijE#H! z^du(ivcplkd|D6e)yHTr<&q>=kCw~lBE>#iF0YbhzsNktB*z3Qc=8IF_f+saOaiQ- z3Iv}Ps;Gf+cbKbT=27CiwJ7t1Bx}l2T(GJLW13Z^8>e~HA{wZc{0O%0)9FXKYu{I- z>gWc#q1~g?jWkxBynL=sUO2}d)=J`8%cHOlNT0F2xc{lr)1l+HcPyTL@~u0`SJheT z#>}bDo|d1uBv%0^u}(%{;PWFvuA(# z{?h(EPp5vg*UxnNhjHTSOw$VdC%gh>qr1Jf<%_{{J0E}W+o$8S{NZN`pTFj$*ZJXV z6S!(=Ysm%c!wSF!>|c6Ml;Yn@y7)EYzOE|DJK)E*8?BKhh{Grx1QUkf5O|@Hjsb|! zVGuK*9emIMn@HP5nJ;f_5|924{6}=b Nmsx%Du9$4j{~t(7!)E{h delta 1735 zcmXw)ZD?C%6vxk#o7&np(t3oc>19*rYT*;&B1W_vVmf1t1yS47P=P7%;;q7lP`0MFwpZHx*MMV{pa`m zpL5T1$-PMzlypHkKVhyM>w1tq=N6x4FYmA3^B7^n@vy5ctyM_&Y&<^ORj!QYjEyPIKSI8(I(F4SHgcZiuduh(P_;&o8S<9 zL3#{+bOu2M3;L6>a6vsoexnT~Q71{AwrO|=F4xYiYdQN2JWyvjnU_htm~>QCyS`63QjUX)a#ye3{(ce3{(cy|Ox(!i~e4xPuO+VEUDfL! zP5h9byfNqug$1-UHwBsk+m0H|je1BA8Lj<+NPjZY9!LfHQV~OMG1~O@cEjikr-FK` z9%(j0`4@ivTWR(^-1I$&ox4r+3cgNbj9$ZIOJvp$L1!zC%`~>qyL$`jOPVEHu{HHk zI2ikKwDr%Iue?@`lS{KL>+q*{*CCaDspOyY4d2}udpqyzUOY+5pB^Z^H|w+0%l*AO z=dyt^tX_VxDrbHg0LWp_@+SiD-(^j#<~=J8Mfnhd7+wwTX#^cYJPc@seh5H>G)dY{ zK1HLCGy(=?T1eaI+)f{ZK7A0Txge2N8WCtF7RujV4GD}2%d@`&{~LYQman<{o5%)A F{|6{-wV?n2 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll new file mode 100755 index 0000000000000000000000000000000000000000..a13680f9557f9ce320a0dd7603d91fcf30645eec GIT binary patch literal 66048 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 Prw`-M(QiKg|0M9=+-bOc literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll deleted file mode 100644 index 329765a8ece422bbc4ae14cf2818ae5e07beb858..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64512 zcmeFa3wTu3)jq!WK9k90CM208lW-FP0UQztcjP7p5WUgyEGw#CR#Z82cG1$v;<~afUHtvrs!yAu z)XCaWi~9cIruNq2s&7$14^`?jXna;XI;fQ@f?R~HQaO~3?YAhT|NK`CJM{9;QPr1= ztNc%HT`DU4+moZ!Oc7A;u0$oGaQ~HSl?ic2wpMf6b>C%Ml;}FWec&gilq+klyQCR> z!lwY(7^~ZFF#ao2s=BPPsj(J}eM29W7vyuA6Ht!fDr>B3h`>?$s?cZV;G2XCg>t1P zAFNR-BzeU@>6=k$>beG{`fX9lYH9k9pqB~vQp#Vl&~8oP)yJW-{sqn*t*FvdGS1aI zhf*2K6f5SWr=-2IWFd@@s9V~%X~O#&rh`T)xHLi`8QB;c+1;&O#35Op6xF(0n~?TcI@>0TXSvO{Z?oH*r_e$3nBJ+)lcITU zFHOWAgcpXxcG`1yYp#?^riNyZ)uOOaNe#W)`@AGkS)No@aCKK?pf&&CifHm!Eh-Qy z7167`qV{ds%cm;UBivhNj8b_+jVi}%!$b)-6+!3sHbPz==>vIyx3MrG8*ij9bb~Uy zy^A8nwDxXwg-Ac}5`RHSnQ_AXAr~CbC8rvvtcw}sGfrfHm5dhd5%0X_59F;&HuG*@$e@B7Jm-2hx}oTew8V;(xAh)RF3QSfA|%27?_a zSaQIFx;<(%d#Y4n{6J3$?yUpa{cTulg%&mqM&x0Perb3Jq=MB$1rO+^Vb~&>c|)}d zp$-SRG~r2z*Pp8n6cl0h*a-le#DJYhjtxPx#P98WLan!HEL_`X$5hBNI|gJcCp=vY zcZY|gew&ua2#7@k=g!?W-_=SYshwA{&>g@o#*UyZUQqH(N(DBrk&&ooP+>|Hb}Xnz zie%zoPRhi=Y~{ph--?>C8YS}vYaHfHcce$=jcjG!V8XV~o3js_H{#@kF_qkTWBF<1 ziFtE6>Xv^d3<>i_aKr@DBF#I*a1~U8k3C3LCza%y7U`@*q?bF1qz-hQWAGj7ul`Q; zi)wMse}UH}897TP;_Zb`s)Zi%#3ps;BaMkI{A@H@?|S*ZJvx#hQu%Nf#Y z`}8?W`gV61^BU7fauUITuYLMht#p-IP9N#YAelZQgjrmsPqG4=)Cd-AnLf!X?2u6J zP9H2@GJUX+ar(4xMcqCIGJm|BKRu*f%pcjx{8=a+x9iUL51T*YNTZ zdg+tXBADFk4=&ukOCPy#VwcAJJapfc&e^dRX{|tE(>NJxtmxlqtd}FOj>ozgmc&?J z43gM)C8opoU5O&O?@CuV)*^&iJh|^CQ*-dXn@mLezU#(}H{I1S(x1O=sRG;HIXrv!dm}g%@O#6TqFf+X zho?xn;ig5}4PzFTwjWTX;zU+21Hnm_UAV-R`I953^n&RVAxyu5l7%Ur4y(3lk`wPT z32+8xE<-}DO0BAwX<9F>pfBPQM&yaUT$$RJjkYgS(Q)eIN9!_Twp+uanWoL%1~amm>=&WmS?pPW-m-y*c2c;qxu zkHg6|&c@|j!w+w%76)3MPS1Ajt#cr_XW3;hFTfOSkFP~6ocR=nn=qzqY4{A$BF>Jk zBhqyz@nTmyQoJ{Z=fS~g?2#z%@L=uVcn&%g!H(k}P{?GQ4N>NPN;1%Ad$Dl0d#Qmk z_EN(=t;Dex^HG9`Q~~BOTM}u6Mc+V@hB$*tOhgJgL|%d5d>~oWu@zLqg_%Fq=FC_< zvsg0P?e$veb;+fUX9N!4&Y*y2kk7fM-g8ZTnJFl7JmH6B`0|E2syp%+z&cRiFU>OE zO^$bycz6rv`Mu_v`r#iJBGHoPBKT#(uXoVz1PU@sv(tT>x_Eo{o}V$#?<<^_=}U+A zN8S=I&vS7`EeE!dGSjayYjE0*iH!rYzm=9XSdgGtW3bOyAM0XT#2j7(N9$r*#2k*o zv83$faANAe()DUw)0zGSjmKiVOw%I>XDc;@jl-Z>jiuI;)HW@$`$@P~a@XO!8J`&U zL#{s;qsS4iKV?FT3#Ufg;rq$1l>G$9RJ)%@AQ4&)+fU9FAK9y#o{^GL{duCA9L6Y> zHeHB7q7q#D{4c<`biufUF*tGnF$W6dpb~i&rRBuD2gVo&7`Z+QHr1mhzqe@#Hi2xF z?zp}efO{hiz|248rw{U`M^LN(9q%Bo*Gj$;rF){!XsK&|Ic$jRRRf1uxd-OQxK7$| zn|MyT^FK6^Xrr)SvW;+=mF1iPhbsPiStd8v2*bToPKEq~OL!&Sc&1DUs*`S!WpD^b z08PsQmzt8xl13+Tp;#LM+gNcEBpfk3VG(Qt&5$B1ME?V4^+nkBA6z(K^~DelcrO7q z;lS(f9~Dakqfu(-7$&63M&6wW4ygXYq17$eV2qG=Oqm{$RiGtuw3cSmrHrEnqfCyJ z@v!Cm13JrwnO^Zv{wA3qnMrOsPt3LW!TSb9@u3?WJg^(s7InAXx5?pk@|Z`n}_vR>?OTy z8cX^*9=0U;(vn}5i~i%LK&Tg{rMKx$?(23`>CAEK*!OYQcfB+q6<;nw$G*E=-wo}) zS9I?CmFxSxcHb*I_brgcjbo9ISn@a)QVz!f*?61g%g8NrkjJwjMWiYrIC5ChNqMcUOsGB*$0&6e>!yln^pj}9pmBAhlWX^^T_C;G*F}&fA0Vn~A1;f(L#$cATjRCt# z!j`;#UxbeHdcT{ijqScyckcUw>w8VR@3o!#e(3sM*Y3NibKmqtt~wb5TzR@a8jAKc43A8SJEEh0Ouw@NV{bEaY*;V6Q2ER0>WG$I4#iSz*aOM7}FT_FTk z{{WboYn=3y#lagXgm&;dfAS}fKUk|Y78`@TBRszSc#yK*Nj)iRmaHF5Q5k-By%T%M z)HSzbin|UANA|*R*TJI(5x9c)9^# z&6WVDNd#c+ZUDA_{zLnR(8`kM5}0p>_gC#c-~T{J76`jM$U)8RlOtp4t_$rx9(!3R zs{%TnH#AL^x@{G;Da?U#q z=}24-iG`O#6nM-iM?baHUxeP^dz9BZJC8jT_9L9f$~-`=at;whDsDsTgEF1QcN5h) zjqfLA6CQ%m!!CEA0Ex19;_X$Yy+#@d>mk=jV`RAHf)U?TVHfneS4KZVw@iz~6S)_n zy)t6ZERZ-qz8jZFax#p`?Zs75vY2BFZ%1MGdbDYrG&Kv(*ipT>Jd)a(RbC!R&(}(? znd}o%lYL@pvc35O{L^o99o$%xfGS2ua#bNovFtB z>WP@wAdy%PpTy+vlCc7(9wyHd^b86FJ-I6KAhe~087r2EIxUzsXkaicS4Y}JosAo0 z*mJzR?~z#=!YwKs-Mqa0ky+|(x*r|8RPJv%stRo#gSH&MXN63sL<>5COFgvUSs{_L zg=5iziOdjnR(cb5ac|QW>04>OuL&m&-lm7h-1^yjZ$|hjC}sUhQ!~((90L*;rLq$y z*F8DGORhWp3mawLbY`}fs$5X8ryYY)pQqXm30XRR;(w)1KyZ4 z#dQg5W&3(E4<07`xYSYhGEN(k>xo!6#VK^So)jl0;vsV!S1{jYJqe(%*b|>X>xZr< zrHQIBQ|2Q3oa0F5;p@qKSPz-w3!!SC<4>Y?cRl$Dx@B4aQk{vEltTBe+JH2Po(x%rfh)Q^Eq5g&Pq-6DXEDT3lmMDqqSswA{qZ# zo}cO@xj6fC@B5*PixEKTEv)*()48OEc|dvIwOaq zQyf~E7)ht}^>n6lerh_gq$cOBSeQ-<9nRa?iTICBK5G;8p^r`IV`@Gx0Y7AVu96_# zB{*ez+Qdk=Q}W5!Sm4O{lwwW`3#aCDwKSD7J;k9_phWU1eYN>K8>+-QFf%ouVqrch zbePYUMEpl5pI0R6Lmw|gA5-&r1^6NP{JsQvcs_SN7joVd}1Q?Jnd#!4@vY7B>KY>{Rk5+@kD-+NHl|HfzA@0EatSZ@GnymeTOua zl4x;gWy<8-L3+Mcddc};(c>6;+$JSUc(Cv&|J>cm1ZD>c_*VXi53 zl2|4Py-jk>rx&A47+mj-RjU=G6 zTuV49xn|5PaO7M|F{g!vQ*-^CG?kKTacC7_uBGS6TvtP#nAdYsb1fF;nnFjpcAWO} zsiU6jK%#2o`bG4(^IX3I>mj**LlV$gt|gq5Tr*}CIC8F~nA5_-skwerno7yFIJ62d z*V6N3u4|x9bWjXRE=D}gC2LD>pid@l55-n={(mGPD-vB zGYcF!*HX-BVd2zVe;`ezVXImSRo|3#aD#3u!7P*W%DBz+6kulew;i zI+5!$Q*$jA=9)rBxjre8kfWaK*@>!=>u=EG&U5`OtcT>Y}5^~gYeL+_&a$%(e79nQMG&lFT)(ev ziK>z7M)bJzd3`aghvXVJ&pXexgp-nM#>@go&b1VCT39$W*R9f2O0LDBRe-scp4(hY z{tAs!y>TCTO@q`GeiXN61L;%p72iNpJ+K{y&oq3nv#BP0uEggqd~mN_y@1aie7?k| zi&m-_pV9bC$7caP_?k!IX1TfvpD}n6M6FrMX5jB_nk|FF%++C@Ywc@9Aq0&zMhv7y0eI zmdoP2-of6m^v(@LyvU~;sa(Y66$Oi6Day@^gv4UAbCy{81pC0!C$~$apIB^0ceRH!SBgFCJSo-DWL{1kA?ulR&*$BylZMIv}?ZeC<{dxdtn zCFZ~r^^@re%H{|8n|csQVrd#fjf7Gec0bt)!iDne+NC` zV~}pQt{&FHeLR?!YUyb$+|PsFRLe2e!hJoMo@(i3E!^LOzEn%^3~S;}AIvz&~kmG(49=Jm9?> zO8Z<&SNmK_S<|mEF`~#_^3D2hlF#Ia+hADzBp~HM`=>ygc8V@4mT)&z748nO&&&*W zl5c&KoZJ3xOzYEdHS*+!zx6i&JY$FNV;zMMRA2Phw1@+rH7zVVsi4G!YzfoyEcAQ= zwDmbirl9qCY)Vfsd}j`4}U*#f_2Eb+si0&gy$AR%OAd(!fTdKHdp{Fiv%%Sl5fCNUG& z0>iJNL^6MP;!EBxS~EH6uvYemP7*BplULn`Wmo?7&ToI17I&DIbGbF#tHNI&G)U5j zILNZ=I=p^xFS<6$Gci1|>e!)MBThS)^Bl`{IJleryEoo04ze7(4!y79{zm!MgQskr zcmx{dUOi9WI`PPClsn8kmFvW#OQYNu*KU%zwdp z$RhF+3CF!wz74Ybtl=Bj!3^Vy`~jkU){rr?Kw@pV+kJLfRvbKQm@MYl!f&FmyGAuV zAWg~jn=C(g)=-kgr1JVrdcIbA&1Yh6O3gK{r<1uB3v*4Oqg;3T?DGGx-nQquf9JWz z7YoTp4|kx)%ry?Shv)j2upW}@UqRJDuHRy=C7j6aM6MY#3v`z2WHG0Oh2KueH5RLb zaxD(6%$PiXBt2g%z2@ChtVEbNl(|ngGkVvd^dJYjQs4*5X3v*vTSJCh@m5f zjTKFr!Yv8a6*mluafZ4c+sv+zXE!(2FFOxM52dcV9Pb~dK{t1{ie1Hb5moWDxzj6Q zdjPyy{3ka=7Kt>rcwRek&--%9ID|1`)a1q9y;(MJhR%8(lVnIUo@_trw3bFhbR`b6_Gefs3ifKQ$l z&1b<4#;eZG6?~f3q5{$XcaGpn#&|0|e??7SeZ2?0rKZw|PcPzaIa0%)lvrB=(udLX z+|PEe&b31PEGRjg!Lm{6-}gNO&C+bi!?{86Z)BZO`drUQM?#j7or^glqmJ>#YiW1- z=jBgIu(60p7+hehM@A<>#v}r(L5?Qjm#i>t!EWqwQT8NQykwVTiVY({=A&o2yx9%U z2Qb!?@M|Av9Bd-%>>_WTffds;3v(|DHnre^yc)dgjma;}wORHLwveT|(e?wE;ra=l z16XI4%wDk917i?Tmb|M0_7Pc*DkAHiDYl?olZa;*VR^EOfnAnm8TK2nAF*5?ykV@t zZVN0llT;tP-@F!ac=bY416HOoU@J8X%~G(jWcg(M@K%M`hLRnNwNh9&vJzF#XwS)! zS_Z32Xq#IgwG37($^M+5%DyQSR;Jd`c3hsYA?j+f9%Mt+Cibi}w9rh&eb1Z7PGUcY zsV(%Jo?Dc&R1H@Tsm+MtmEaN#@(A^F+SV2&o@3NIWRr|#?~?7O=NR=KS(VG) zC;OAj{z7)S$CmquteacQ-^nJr>{GHY-EyCko$azO$#%Q!8?seyo&Qai@7AKUM0BR> z>5#qQGOzZ*_I;OS(Dn@3SlmmNaxWE1KgX#c*&W%!#;Xw7ujx5nb=7`&Mv>d4YJ%!{ z5bJ#q>w6IEpTdq;1GPad_hl%x5oeKu$wpyU+o(=Z6H+|O)k!IAlA5X0umC&-&u#c+ zg4rxLKU=Aon&+}#!WL6!sYSGX5E3?DT}ZYY2aA|G8}nFNzk}r#sB6jAv)noAPO^!J zFQyi%`^hGeRjJ3xa25w!wR(YUKUt01O?EcfBK09z6;n82LvoB7)EeXT$x+u} zIjq6{waz$b{ZXu?HEO-Of^0I`)#}<5c8%I(9PCwL95v^wYt;?3ok`DY)m>zMvg_1l zlN^;zY76@!V|$~%(Pc8WH|m?zLn%GGSv|>Gl0m^Ie5f3qw-&Vd6~URm4i-eL=B~ru=N7$XhAjMBJ4vnrO}%|Lo}8 zZ0Ylc+-uPKWMERWiJDC*n$CUtsLE{dugt#5?^Ro}uK}*l6aT#Q_dTQ4PkpyRb9crX z;7b{I`bVp|1$X*~sUMin(%SJp%Kz})=@tJiu!=kawcYC1W@y!XSp z$~*-9-5HMnU&?sO@AdxNS%tXfXa5HH%N)TELV~*s1@EAKJ@pffXeJTA)FSUEo=vPG z?k4_;SW3^K#C&2m;+eF*0qmoecqNlBcz+9d4{^WuPRLR3E5IGZfy9Z#&1s^4ggAmY zow$Pded2y%F8yDmypMPcu?jdsEzEucI6pfM{AJGjzz;%#y9=KJ-jV$oaD9&8L?bwf z_@x$kKk;m06>&H5PsCDs4khLjyAjW%^$p-?b-MXgT7kM%HTVitk$M2T)nfmD`LtSE z_`XN0KYK*>`U0@1w85- z*Y@8TRSwQ-`zZX|;5!|jUWKrQAtIa=scx?A0@%`3AD5Y&M@+gJ=(1qWfwXirJf)mZ z%}B7VI8Qvw^~?)Z1^lWeVMA-G{vdYYL2TtgZ0$kp$^^?nEw@_cyWca!38#|j$9GuNQm{KlNJ(plxac=vj>v>OpRUk{n6Sl=*-zM0SK#mIawK?mN{Rn=& zQ*F$D39N@@dSiZtgR^e_dj|8iHE@g?OWS(H_o}Ctnv`H(e0M*cOlHr9KyP&x**f2< z+^OC^s>Wqw$QsE0tRD<+#6Gq)!8Qf@s%Ob=_Pv*LOQ2YF?I+FO?0XfgzdGMCH6#13 zz_F^CY^}PaU|S%penDn45mxWG<;E5K7`885Psz(b^|fpJxbT)hiAw8lTZn@VQrTqB zD9KBi8sjp_OPM;2?9a%{gMlIHGBSzwk-$)OJ()!N>%egJ1DA~<+v=8+XostJ5^NV% z6S<8e@x7Pxd|;%icG;_7qt&l0L$t31#;BLcY_wxlJ}z=(#AMvZs!?QXmBcqzjUkh9 ze?BlyRk|z=HbI^0mXr7q!eXq6KP%%Os)&>LfCWNM)X*qGUI#rwYB93)Pck>o6m`WLB%+ zy0#rTd6_jTa}axtI}yDz7pZY%wr7jfG%}m(MQVoiM6UZ~)~YjH76+?S)owYNJ?E)L zmr2jgQ&*8m&jw|lukI$3z6{T-S3f3`%y087QBRQFtajv#$-F>4LuUKZpk5`jeQ8i{ zSWon&Jaegf&t-A2i2B$qCw;k49dMcS6uMxl4a_4-@MFb zb*AgNG;bl;5|>?)SC_d$wI<3nWL~7MOO$KMyjX2cDR;5jky7pw^&7HXK3Snxs#nQw z_Kho8nYmKEonV(`UaIzy+1Oju&@$=uF7CxGYAl(|`R`}0Qd3+O2V1SqBC|6js%l&& zu}4*e?9W)sZ_30>v^Heo-ptFSdi;9^XCyz(T&J#}P1f=!GuNx@63nYESGOkE4W7%@ zkI3vXXM=i}Y=du^XQ$bq9&_0W&$F2u)Go_Vr&nE}UL&*dU7?DGNb9?Jbh<)KC6oAc z+V|8fm&L)ZQs5#=)W68M7G!Qx`9o1mZ&LoW&oggO6NF*D{KEI|%$wBtWShF?=Y8(My=?w_Cas&_ zbh%kAp-tveewSO+rEWQyJ-4YlT_&^V2kI#@I}2`CFOl7#1_pa}xm`KKq|&v_(j6+3 z%x38hHIK~Bf;&_VnPjPdmmjL7E{lWRrPjLTWDnS^u5_7XX|uY8OlHB5E_bV#wIOGX zUACy7x}F;MNw=y;$RuZvb=juc$ZYKQ*wB$(i7&|{z8|UA=y|i+?|G`rz3MBMeU|q^ zm+fl7a4CAT`YiADE0#x%6;4A*Xp&Da!;yH5}xT^Ht6@Ru6 z@kt9$s~)4;qb5+@6VK<=w1j8>tmoCtgy*2F7u38I&li>a=Df|| z$gG!COTu$}*6-B%6wlwQSi-X+>lM|O@H{E&RrOAa=j-aLgy)>BH&nmTwuROH1zCSk z^IRtVd`mUCY`>>2Yqx4ics69ct=6Y_{!!hP@NCZdlloD@vnA_Y^+1Z}9`!=Pb6wVZ z>eYnjRatx0J1L&;t1lCt*Ju4%eVg#SE$aj2JI?l6`uU;i=d%5t%~^j{l`dQD-=6i6 zs!s9zn_89dd?@Sh>fVIsqgkJ*cTzk*RbM7NcV>O2zD;;OpY>1W8{5zy`19t-|7o8JIfC!!*8)Pe_#eFw4<%Qp%<2=9F??eUWS1@A)jttFKO! z`#LLK-TJJ$J>i*^9ngDIJiF+BklCJP>CY48dS+*7|G4%!*e^RFN~EkiIqHIWfCHKc4WMmR+dhDW2VQ;dtBLe$VOI-F0u5 zt@h8)?x6>{OjZ^Aqqn7$>#Ki6X3t;x>YtO@ z<4Uo9%G!KSIP)@#_46)!*10&lSieSQk1PFj(FEzWJ+AcAOUUH763y{xvj znLYXr)Z1Mq$CZKl5i&Wh+?!dV+bqLz<*Mvb{h{kAXBUI?r(|-B+mt<6dykja(N|{Sz`fC(88$u5G{Po$PY`3zx0- zzn?ux?@B3Gq5qXqu2O$VCUZjLJ4tW3v|uwhMdy-j@V(+Z@0p^zyXJUw$}>2)p} z3ieI45T7jLFh7iD+=n936659PA7|kj&2VdHO_`NksGX8Duu1vvieZ zi0HVS`TBdVr$ltNzK%>HnwYadZzGe4rsSNXe`*;cTBx5Ovk_J4=dH~*5fN4CS6p@y zBC68wklBc;b+|%euwzuM&mxnEPR*&&buNp8)#{aGHljLxtIH&!I(-kBjp$tcQ_B$1 zyqxp&o35usbiR(0NkmmS_4;3AHlii^Tgza3tjh&DtCBtAbxwosPPV}}&vR~0gYN6H zT2BMmATk@#QhkXn$1z%}x06XkD{_|UpSdg!wp>5wmXlf6sQ=P@F%Q2!$b?#JYPa?WEr$zU2SsbiY4=1x@v__xqGKpx7t|GG$ zMfLfXA)<$J*6K~Jr$ls_zKu*G`en{K{Sz{Ys4Zu`e%vxfbh&O5^x-0Z*GKuInIp5P)xhxKLmA;eAMzm4?%4HJKM*RYr zjp%Cqnq`RS_c_<-|8_kkqHA^9iPD}#^k&X=x;vSTXp;_G#)z)h$C25HZqOCh=DQhV zbb~(0Wp`qXZqRecY(zKem@UUKx>5g?Od@(W=O+Dy%i>_SX#aHSi;d_uJ7QDg?;b=H z(~r39Cx|Gf+sJH0n|0<4>8Bl|&H4;7iRjCmyY(WM#lg1fi^yz5_vo8kCK27Ew~*P0 zex&cS3=!$zz4~?6QzF`~|41eg`GWtYKO?gd{aCA$q%U$jx+&*AolRyVx?lIOHeX*v zbiXckSt%mAUk@U)5&cA8V#{%iexjculZdi|Kh-a}EDrXde$Oo@E5pNDpDe9EgCo#O zVA*6gq8+-cWr(O-@Mn6G>nRcaTu&#Hh>C)b=!Il9qF?9+%NWrwbqkq|=uv%zwfROO zqDS?$E;}9(J*sadvk^U}_t|oc=rLV(iu6+=IyU&Y9_O++*c19xGCM|Xda27KqBh+^ zW+Qr1ueS^l4GTV{?{_^VqMiC@WD?Ps;4b|^Y%eoJlM08s4_j)v$jp!9!X&EDWRnI1~5xu6Xtj)I@ z5xu6*bJ<=*^qO8yX2SZN3AD zXper?W$Bo8d-OYGHlp{m{DGVHmEk?zNG4+x3GUUaT^0v>UtdpVBl>_&^jG~gnM4!~ex$QzN$WPEk9AMW7}4K!DVdGv@A^1v^W|Va z`nx{CW!(_b-}Q-PHlk1TjkX-e=o9@XGKuJl;6L_)>Lp}$jI_DZWim$E z+(Kp}GA3pjBHA8w%yX`%MC38QCzFUC2&S1oli7&8=5xy!QMz&FN?&Y5K9fzh!FL%V z@|i-HZA3&qQ$%JX$}kPK9LFfb{G3c8dL-yKPq{1(mTBH_%gGpJnSZ%VBFZw(8Pd9q zDBEOOhKQaF=9p1r_Pj1=jwh3do(<-jS!6b%JX38MBg!`sG8<9Iv{;*ODk2J*buK#% z5rxb~G8<8WdDE6-L>#umR>LWHzF(dC_GOQP{jqW+NJC_F0CAJ`I+b zE@w##c8p3*h)g2-DmciLklBa^n=zI#qB1j$%tkcC%(gb)&#~4GF=xB%*I2!Wn8jo^ zqM_yiTaIHi)O+Gx4{vnJDH7Wlo{(XiD;CWMrI=#ZBDZc5oP2a zXI8qNGDc&}S~7_!CwHv5naoBs&TO@e5sfzwli7$Sm|t6)?_)$X!TiQ$|3X9)%*$jp zqT@}^v!&N|jE*_=W&@dxXtLSnGKpxid6>*bRAC;s3=#Fotu*hu zo)Xa%^EWbyD4aXhm<7_hjcA(5A(MN6Lvl|vBNvM8&w90gOzw2EV3B2Vuj?dpHJQDy zak9DgAa*;MoE>`A$z}`LIyDgAESzlKbJ=EfvF{Y~Ny1aBQ%y##w6I5);+dV9246># zU0e8wnQ3mdEW=y46D;Q1_J_ptN3Lyh;j^&qaBa8czGhA{&SG23A9DX>PB#HE+p}3F zk8B;jcYY>qmYI}dn{B42*k+rH$?Vw9G3&@AgI+bqY$UUzImf(dJvl$;m_1}Nnv-+q zn!mX$4tA!|b<#6CnrE2|m&s_JWeUk;G*8Z*Z;Gr9qgj=Ewi)7jYISbz0&^Uhe4lek z?m4EM%*MCSoJeNlTWIc1u~nJ-QfyUb@%hphDYquK+BA{bXlu+GYr{Rq4Y@Vu3YR_W zYy`WG%*MXRykpBT_C;nuz0@hO-;`TxhPx~dR%fP?+1SrBbuN?G&olD(fb0>WD))S| z$}+@$S8l!8=6Xu(OU(UbG7k6TUSOUglbL*fZiA8czidQ5%Ux>TC9@GNGap$S?m0f5 zyUhI4Wq!|7VE-nw5k<_2OQaUNZ$`}ZWD?N}xy#L+E{lUTnuo}2M9t>+E|Z9w&AVhW znpL?g%wH@+M6c&wWP%q+3$lKmn|rb8MkW!xlY5CNBa?{s=B_jo$YkIADECrxoy%7H zKhJG3U%5>7%~mt8LF%;o=4w+)X6M9eGm^~C33=ZH-=z8kE3*Y}%Mk41mv>gGDYp=< z_09sZ_6Z3-;Ssd@kAfoqE?=+|^%!L}R<`=b3dJgDScCLXG~IFqhoEMoMza1?`C0aA z5Pa-Et-hwF0ve;PU|HJ-i>YN(V+M-tfyH@_s)&Ku}&F!O5kt3tFm17#>xc>)z zV_943KP~$VXCwYp2Uf+swU&NF;7(|s#$8fIs?7ANS&-M!!Jr~fc7f~J@GF(JHUWF!U09K~6MqTpqdufOR%hjHRcnC{noW8l?iSvr;K}9-+y&gMzrfwU?eO>FUZ3D*)h{E**+Y4c`kwC?r`gDx8X^yL zp5%Kr%|_mxYBus-)G9N-V6OP!8UI!07rw>LW)&}70#B*!Ez}%R>kaOnIUnk8@-{dd z&A5Us&ZqkCIXfH;>m$yMtl>tMy%BZ3=G;O5t<-O&ek=9&QNM$@3s~lnI!AeaYu+rJ z<@r=!mp#w(q~7dX2+g>HMp*ZI)_7in=MA2(8ROSFkiQL@a|?EwcUb>Btp6R>KTt>V zAI7tNk7hptT$%s4XBaiZ^kw-w@x;C4VI$v&dXnFxZ3I?8BkzC-;ukWEynn0BcHf7d zeQb9hvzK9hoBcU7@}_`fazA8w!havy%>zpIK4*VEXMa9tfBtRciSK_KdD8oH*8e&C z@HzYNIa?R~s~-HoQrA<`E@X_|fJ@Tu!@cQBXx=QmFm1Y4X&0sSF(=~v#V7S+q1Lp4 z=vxSH@$2mMu>K+Ry)=&_&zcW2{_H!`x}ofrv`k0dFU@r1jnhm=?osDES$S`#1@&+6 z=3`Gs-X-3F3{Rl{0m#zg4nD;_h}Mztzri!oIS%g!j&y?AJ55l3t4DgJ{xRO5uGPm= zo&@X?~$_Dr}W?S!<3t#ADwXteO5tE&saNJxU-I^|o^75< zW|YCBedf08bfC%al0JuJ$C~dI9+SSnk@>&Ck(s~1k=eVLn#I&Cre->_?NtrbH&EX| zeKR%9)HGAGikel_tfFQ;HS4KaPt8X3c|zKaz_-)SLd`j9BYIv5jXcSmiKxB!wcmI1 z>LAN|!kO43FZSKRu^VgRq3`)7IP%VLjd{UyKV*4lc!DGE3{P<64dDrnydgZnkvEF# z+4BjGyhS|0k?#$5a31d9Jlw%~xP$Xh^sjpUZ6td)GKX8)^R4XpR`&cpYVM=vK5BL_ zmL2SW7LE~JGqP}G7z~`FP6p0X7XTNi?*XgTHsE6QDDZssJ79x)6Sy3|mXoEL)dAoo zs)s*Itx{uvQFVgfhhH$53cOC81iXXty^zyXjy?^TuV(?f>N&uk`V3%^o(Jrw=L5rf z0dSCB2pp=bfg|-I;26CaI6zLnvxuGWbghI{0-hs8W zu5(fR*Qpk@DzurJEiQ_F3-nt;Pg1iJ$NNxdC)?Ty{qvC5!RJ+K_Rwc9e0m4=QnMF6 z@z7rSe2%k;{sE<>hnnbU@pQE0#L+D(y};2@TM?~&h{g0NrcW_^jwvXnPe1*Ac#eQR z6e_3ZBw_{qE9hSV|9Gf^{?q9>oBCSlD+_9=Z=${#*gFtq4eRs`>VkrGwBA7f&D3u} zspf($)Nf_$53_6=txpnn!sn`jo%DH?W#iQEq30gTd*Sn7!Ctnqm!2Q$?rKIz8_A4g zTGVd}93y#1!yDE^0~yrkK@NqADEA>28_8ZVeTq@)`A{)S^)r&0{?v~kmeYR{v4W*4 zsINe&KNeK5)D&v)Z5PVc5NqjKOMNXpYw1}>O%pH_T5F`|Yw5oZKAysL^jXh7tf%#I z;OM{&EVYGoZgJ%nRa&@({#)s}jrxa)ZLD)A>YRnM7|F)d)V~T0h4wy;ovddUJ)fp$oYpw4due^2`VU#dhtxYB>2n$`aE1no zJsf3MUZOFwlm`NP2L^g1qHm-1d$me${={2@J^v@Pn9LMKf!5>*%?Tb*`h&<@DJ?c^hlk zPXF!nZzJwxshupflb%mgj?=oA*1gp1rS*Nv9|C&^KBNzRb`Sk=yqtkviOBJC1SuEM z+J{(7pJM8Z>C>O`Kp>)~PdTxIo)xrK&~pmqYFcX`heEaVsinS_K6RAqfxQFu^o+tM z6pB(_NB?#7Sx5iNDaUBt%u-wEvxWLC^x5W>Ja4CUJ3ZToJL$QTo;&IJH03z0d+5KH zK6|O(OP}{Ce@N?x^mNjhw{+$$oq40&Ctc=4F|Eba6w}(D@<1Rmmd-tzJ{8ng&}Rze z8rD!tYb`akwAN9s2O>+XAqt;RXdOM*(YlVFms8$C{T5f29&V$&9oRdtoi#j3+)2-! zwC-dLPgCAQ>t0&-QnQ!V_bGn}#9X3}<6|~_%!ZHIpxnnNqfkt1F*U`s_NP1$h-~<{ z*U+cJMX9HPo>S;qOMR^?OZ|0}>sdoRYlsrp(Q_TG>sZ6(lw-7Rp}d9qZIrhIkquhg zh&!p@NuQ@F$En|onz4pc^FHxIATmI!%HZCV!L=eo`kzKDqQ01NafbA~KjjJ+MKgtR zEy@lJ)MapefCi(?vg>HQoOmVmS5hBiTU&s=16yd_M%+owPRdUcp9A&|JjYUdY28cx z`$PvnuZrFhi;4Y-6~rmTYQMBnOSz61^-H|#C|~ZEKF6rpLQNaxos{F0_fl2?DW!=H zetTtTponrGVlg$7C|6Lfp`QJDHO6KGYNw%c1Wbm_)gPSWT=U))J${wZwJA7;!UkOQsyHwxFI+XiKKVwIx%I z6m7IVN!&?{6Za7J5>*%Ggy?jU9`>PJ+(qh{M7e@;4dq(+U@WMq#hd9lp(r$12WTzI z5^H&u)LBi85@WEuK+gEL;5Bh;gFI5ls=XUyelAFGtQ#%BiV=d~#qh^@}0* z4@7gMHaxuuY$L|$xhF@Wz;DN*HXRh%6O?+2sOdvZKWfUUnM6$`HPzHCrW~cbnbxh; zv;`&hC#l&5P5;0i%KIpn=ZbZ0uCyB?ZYDmND}C4p424u4Vdp)w!mnO&pQtfyu@H1oU0sM(6Yf`VL8R=CPRwu$A$ zYGRZa!_OCmLNUs1#5hqEuoSUhfz(!BAfAoVnId-hnAEVqxj1yH@ z^eW7HC>K#KCsq@q#2B%S7$>TMEJZ9Q?iwiLzH6Y2^1gx6dbC99kCupMjMzquQy-_S zO4)}})KrOqfdF=87rPE>=&XIpu1~)s&-@qm*OBHe#GuG?aZHRt}XGD~C#p)zmB=$`PR)Beo5dcH1b& zDaR?RVeH8;u@+G-r(90CnsPPeC^1HCBkmg}?d}^U?W*A%+2K-~XSlRpM7f+;O=~sf zDCH>S7_p5QC#n(b53!tBO^g!PkB}DEkB}B))NCCgZN*1O>v3w-NY+3sA1V5B%GH#s zDMyJhVjD3|RHImy*l(1y)o+xvRZdOiC~2#ja+KIMO6qT;94D&LtYNh1izt^lr6)dB#aw zMbz{gCvBBet|mr_F=87rPE_OBIS7_p5QC#uOTOYApU z+Uhr1+A61}aT!tc_SstR}{$O8qg)ZNxZHO%uJECZ#;nq!rIJX{CtzBI^51leWq!R}-Ve7_p5Q zC#nJyGh9QjQU~o+zzsJyBX|qh{BMQh%JDacb0b_G&t7BbF1ZiBV#V*hY*K z_f6*+@(ji@L*ydL{U}$@kUFcWi4tSPHtO3b$0^4ttCQF|v7A_WlAIS+o+M}8)zn0Z z>#1K4eg8m=nyn{EL~WGgM0K*%R(`Vdp`3CxF-nY4AEVqxxs7t1s7_%|h~>n}Q`nPJ zq{V7#7M~(5Mk&XLZNxaS=u~O9=v4NBSWS#lAEg|l9HZPuj1%{rDsAmMRoYTBr3TMT zX{(5GIkB1;CB}$t#Q02(<7sT27$e3{`v~=@(*?_k)x;<ND7X%28sB*hYOD)9yB+Ut<;QTOfAT{# zvXvi*k*)lUi)_o??Id?Q+1*yS+e&vk#ofw}HAuPX?skT|t#-E;sIE?)k zzAybO--Eti;FpJA^}Xl&+~;I?(O$Z8ln;L;A_Gs%_#p)$<>EWMJe8?J{7Vn`s|e6` zho%QKJ@Jn|#sq&K9eccNB`g zFq8w$Ga;!bni~R6AVzb$Q5Nh>Z%bKR>FEW}RLyUl;)Ev4GcX~)>kLWAV?84h^2`+Z zJkPj<{&S~1ArJ5*<-1e#52eUMQshY~^6Ms9_Jb5Tkm7Spio7aCzAiTMhz%IaC zFpZg*4Y>e1gV~n{?1h=BF$+VG`(lO~%))L!{K`JC1YQPnu{W>`^VHx8t771Icp1#G zV}U1Qz8cKLQs4s2S%X+|*_W+H06tft0>hZuKc&ba| z+x6oiACD)y@HfNoT$ffS01duBuK>=~Q=mBmXjHA923)MCLsJJd_=_+n0h{zG&@=-L zo`0GNyiA`C%{rh_*Xh~7O?oag*8`2ZOP>jh>9e5O3^eK|`fT7&^*PWy05s}Xx(fJ& zu7T#)K%;)EYk@D~1x5KC^*YFJ>+^u`=z3`W2sG-i`U2obdMPv?1C9DxM}Xhx3!&K$ z#Mqf8V1`)%jUOm~_4#68SF;kDZa|EJX#pNL8jT&Xv07sj(&>RQE`y==^)Tk-u za%iRkjhbz)0M0R2LNga=)FOQUioBVtp;-(x>OylZu+eOSrU_`&RptiZMspMJ26GE= ztGNxh&D;*3dw@ngY<>vbVeW$FXTU}HOHYG=xoJay`S`m6i&R0{2w>N=QNZqL#{qk$ zjm1nEju9{Cb9r+yPiiqs8u2{aTKwhe>(%Xe>h4kX6rQbnMZK*)QvX!@m7_CtS6!qB z>Uw>lUa8mWEA=LQo8GLq>j(8O^^^KJ{d@hE-lOpg4Ek%WO@;}Y?xwFPF~^ySW(uBf zn{DQsMfj^H7n)1V8neM%V{SG-G+WJM=C@{_`J4Hd`M1e%PH`@F?r>go_Belc_B&lX z#hwA4lRV$|{MhqH&sUyaX~Wa5O}jVkcWHk~`y%Za@3G#iyf=EE_2#9|PG6LMd-~n! z_oe?V{h9RNrLXoq?|aMlk*q5WTW#U#TaFgmH`rW6umD-(egh!Z=2Raf}G#IhwGl!5+H^$BmyvhHjF9@}9aHPK%hiAC>X&M<=io1yTfbZM z!$z`vi_34r_8fJKbB_8DAIEc!3VBwlsh)L^|AEgs@PFX*WA%yW_i9esk6~-jpMYn2 zM_@Z1pHuL;QIAS*z~@Fi3EN57&Pi+Fr^#nQSY zyKqHKbGu23pV?U7ET!huoOfQ`VsQo$!^~w3D`zjSStd13L8*rN=9RYQx<=}3z0DC} zC)YPMV^g`PBC@Qx?h=uwju@_{<1-f@sc-J|WzDW=r3tl>70a3@j;g8}uBNV7R$Dz> zrSx^UI-{mxMcteg%Mp}IW-f28k1PY5Rd;SeX4Avfq{haYl`u`Hml{W?siQ}#>G;gW zr@eVsMDt=ChCkARPrK0-VT3e&_$XKfQhEXPu;F7+2yk9qbJg5AQ^%<3P>f0S8Y2@% zO*kd8ctu0qM1>UA)-~5Jt*e}zDwj>3J!#IVXnc92m1eJOYOY&aHhm`c^Xbc$)iusK zQ`NiMDGhZ?>y|Y`Qm-q97XkXA`ZmT^2n?ysi<|xjjlSu}zLdT)mZ8&x)mPB_fFCv_=ee zZL`%Th*&r)t=<(yTe*m%hK)?9+0Ba=aZ*vh8l>F0P!VZpsH>GJ-&8iO4pXAOmd#bx z*POR3($rjEi=T#AoJyqfiWQBGm@KE%EUUo|J?H#J?0fK=FtMSks(x90bA3%iLMd}! zO>e5KJGXvW-D1VvylL*Ti_mJMvHnu1CdeF{ctKUwC6uMIGo;X4>J_Q|g+UFyT5fG@l|r@k;mb~=I5+B)Vqvp_u)O7-eeCRH4TT` z<~DYqJf&{wqPoVW!@Vapo`-|$vgQsI zlF~}MvYI$0)h&`1Dq@k8tT=R`IHpC(VybUaw%Qt?mb;hSwN|_9-K9h|3c3p@fKoU> z0?0rVxPS^cs0uhhQnU|EYalNH@{j;U--5P}eQ+Ndq$to26m@_9nYnu}Dalrwr=nSj z_spDg=IhLvbI!dpcek?j5PqT430pPO3j4i&rB$nRYi6a5O^}ml;zZ1GmU2H_YKctt z<*tcg=uos|igqYq3@#kqyEcr(&ir?#M~UVw-WvP*pZ+ zOpiHHYhXNI>b7rKxi0sGJoduj)m7$=G$lhDf0>0|4;^dXJQMaS)KXdK z^Bccwo2m}gtJT6}xMLWjF7+->#vsqLL^S1Sqw z9&Ukfd%dxNEU-0%w`CRs<+X*Z=z&RaPv(2ZGKyu0KA z3_^zli5Xk2tcU%Z7m0{_aS>}ad~7Sjksw7QKi>_nH^LiU)e{VE5!hj044aiLn@Z4^ zv7*}tnjl8=#or^v1SeAG z7GkV5hSovHxFrVVZp~s`+-Yw6S~p{Yw~F?rt>0K{=ngJHl>vY0CMHHz+QdrR0$FM6 zI<0j~xKh)N-KwSGe;ng=MdL)0XTuF<;yRWR6`*i9cvE@_UhH0<8PW3(FiRI1p z^+vV9;y$wWgblWRLDySE5LT}F>di&` zar>H)BQ^wk_Kw+lbT^As6INQL-C2E^Qu1AOmpzSbvFWAW=|&$Te4@pjL(9ma>Mq~- z2{1KpOrr5HhyEtSoT*$5UF2jiq05_{PP>aiz^8=P#BdMp!l84U{d4Q|bR&#u%QqVR zYCX1cF=eTR_B3keFxYk#$CRkP81sc*yJf6Gcf*yoBt&2)GaGgHbffhK0STVNdGBte zi`L4ID|OBCo0pjN?oFwE*u^zJySj?7ly>Uo&0iD?z`mjB-hiRquXDBc=We=)*}7&G zQ2?}f?0WSb1Y;YrF1~AS=t+xkeGI_$5YcsQ9jDtjR7cZ-C{V*GMnj72^5`~jCSt=M zAM+OU1@001KFoVe=|rg=%nRIRUY92}GrINTYC)tOdQ4%KtMyRNG#2_cyNG&;er|o8 zM-Yy~J;OMw2TqM@FB(96zuL1}YVRR?#)`$KlM6g57MTXS)Y_e8Zqggoa8zqVmar8L zjp)vsV?eY5d$J%Mlsa_=HX@!x*Jn_y}up3fpuMJRIk!}t>zM1%`WBcz#|DHX5MOwQ+El`g?v%| zJm#_=Wt@(~^fRb017G!GF=qaBZlo_6QHP%(c-Ky=Rt;9=AjwDJ9{Eo+z93X5j;Z9qm{)fn7J6D*(Ms0Q*_e|*Zal>2Qsru z*E&sHO&{NPVv7~cvd^(K@XvuBRW7mv8smqseQ5QP`G=HEHj!jK_QH|X)v9|$g&{{r zxms(;gy~VPIm11P)?w7~6{WB9X!#WaLDRiqrRriO)3bNdlspw~q1hW;wS27+2J0ZR z6e)+Du@J6MV16COZZuS2kZ{*T~E+u#dK3 zaUrxmxNGEkHnm2XGNsGx?Ho2o3@0-tuaj@W!B?CGwV?3=tT4(+#I8OcGCoHJjdmIiVwQ+m@%ug!i~*_LeCT0{{>a@HKE z++oU@kFBz+R-wN&xI^mbkzY0DX}&8g>_^0I2hxXZ9mN(2S@ll=jmtL%C{;xer$Vw#5XD3lH^dteQ|n3 z-@Q!fE+dhAG;eWk#54X9Ew$DEVw4)uGE36P-MYrOOBSc=2$z%gqJMiFjPcSm;T??e zOPo45V)+GQyw1@G?_i8yq83gyQNLh}zvS@_j_~87)x<2hbrsV_+Fy)PF>Q&~?MkAY zOU1NHBU+Ri(Q+q!za32CUB6Fm?>9fb((+m(?JF}cvLI!T)7qET^;u<3<7F)>{K;DM zz-k3FZAoWAHmOgVU9l^(!g|uW^ zOh0PPOPf2?ZN|^ivRy5h!;jzj-B0Zq7G8QU?Ec5~^RM1B>2eU{$I2$ikSG?FEo926 zpuiQx348tRiT$N8*k8I5>@!&WOGEm#`7>ELk6!?G&|Az9#dad5{o-1YDs z4i*M`{uu!&rcTzZ|ko#xL@4TKYI1uyh}z`P=B6{ zGJ>wP!F}KAoQFp}ocHjUhc9}#=;0|3PkVUY!xaxNd-$4%S3InFSog5$p{64YO2fW~ zzJJ48k@(b6=IcP0!F#kUWhh-hVN+uM0hn}|vsfUc0hVRFY&Y7r zXHwbJWO>XXGpSUD3J1fnTri<=y&p{G$|(*O(l`X>-L_O$jZy*_icL|N7)xo2Vln81 z#dL(}CR^mS6yZdF^UEwJJ(K2O_IV>3y6sAe13WdV%+*t8e@fPH- z2gO^vM#F(^l7VxGPPJ#$h!`}(P;#khNh88cL${spFb5OqEJlFdaOEqy0QV+9=doU? zDdxkQDwWV;9?R09y#dFC=qOnZ7$G1#yHiCwo0iRUPuTe!S%LReA{XRyxpW?TkQt{_ z-$@mULxM<1rNLM7Ok!#9RZJsoOdl{A#5Z^w86Pkcxv|pVFCe0HQrzKgw3W2gg{iC= zD-@=t=(#XcXo_U;F10cyJA;_zDVbyqes~+4T@&9mm9Ul1rR0N#&*T~Xy8($w zD+YLr!-LE#D-0pLo;&!k&r15H?P=-O@Mvi`Um6}O4PPt`7fZuarQzw)@O){wQW{<^ z4PPq_uat(h(y(3{HcP_}exx+qDh+RqI|<7GNIGvL9eRj1PZvrTtbO`6OK0%5UAk{0 zYN@LbpV%v-s;P9dXC?ma)B(P*Fgsy6QrSEUH=oUo<@W{oNvu<(FILVrT#(o`F9j}QI*g{R!jfD6hu3BdY{3KrW=Iw4OjeS; zWNXe|W^hfD<{R9a`zU-yg?Xm&oCat7in_-)SXHN!N(&KG%-vD zaxL(|BgbC4P>{8^;dH7XOlsPK!Zb$ROi$$%s3_`?sh*St%}-&8^27%?h+?f+%iyWF zmJJ@Bbg`C)4h9#G)5dK>Y1$%nTclpB+ah(#rfVKYugYMyILF-?@njZ+<4xyyf|>nYu$5^@+`8!bY@(24+i{aNh>8cC)=kk%R{sNzv94G z9qFDW-OCeb4c>$&O7Qz21W1@h{#y@xMcs&^eaebhbQ0T6P(}FSUzwAiv$3C?K5ks5 zL`gNw3m1xurZWT*G$hD)@aV-k`QcR*%-91}X7k;Tk`QcAAS`E9vEMun^K2-l0RXs94lWHa#itYVd1oXwFP zkF(=sC*v&PCQ3uzhe7BYh)x30p+Gt=kR~fq8EMN`3Etq#xVR>!bRbl?~TU@Uva zdobF?6E#A{w#!{=gmQkDcJr=P-29xYOhAi324HVqRmzfPu~7ixY0B7?R;WUQqpp|$ z#g5WYus3EPaF}-t0x-<8<0QeP$ zCnCD+@B-j3J3L|1YYr~}{xyducDmy50^qMWJONeB;RV3g9G)mkT8``mz}Fp~(5vb2 z0^pktPdwIfcmePohbKtuJG=n+zQYr_Z8^LEcrWf-M05@>0A32u{KP6Xn#{WjUSs1Z zv#n6qmA<>(YPVAz%?RxbN5wa^U0QWmy*KfO0JQt$WXer%sr5+Ge zyHWy_df-cmQJowu2Qp&^`5BFah5+QCNs*XVZhDH`BnjN>L2fiMq;P1u-h-0Q!osou z!RW=d1$N5PZ`-ER?ag^zPLmNE*|@@(mw9Dr=In_T z4mH?wg3tKP`_ElJGIN+33QvtrMESQFv;$gHk#ba~3@cyPTj1S?>Q$YcDxa>b^^DoY z%a)v|2`jyjXMy~B&XKtzJguz+=Czf2SWX;{3+I=5<@I*g zbM)8^X2a$8?C$<7d$P%VxzQ>g|0GX0)$rk&IsG%{vw=BcGl#m>!=J7^S9z{_bbW4q zy*B^+TsXHD&Q~i(s-LMm|9rK&_Sx{+%F)XF;VKWOxuc#;bkU0R=>)Yf1U=P&b`++{f66|DMZn+p9ZQIP=cEL%l|9=>OxM7^iMF$XhlKY1Cy+RePJMLW z3@?0X^3&Qr&)b6&oUJkDM!>sm#*DG~KgOw{oZk!2*bUOGJN1&*8Kl(GeCpEt7zggh zI9@--G5;|R^^b8_e~hE~X&skO>-~(hUXV%aQ2iJ$2#j&W|AU7=?D6Q$ZGE`Q6Yw`e z>Y^v{qMjr9yuBe5E7LzI=sy2A{qKKif-~n;@=y6AiZ%Iv_C$bc=XG5>%I`t@UV
    sOnVO^lcRA#6aUS+6CR zKgTXOGZW5sI5gd;&Q>|T6!vD<8l0?ZZS)RRIb_!D%vviMS)5r8sm*%xI-5A@jWJHv zyxmOAba+8z`P2f^Hont;{0ZM_3FZ&K_02c_;PWrG?<|e~V7zDrZO8garOU}-$LakE zK4Vsox4VnY=9x;PWv+3|wi|}_XqxB$;Mb^TrwHS^{?DfLcBI~@G=uF!aFz!*^blTr zr}(>E=2!o)fYGO(#z&f0%rg6#udoYuk<=1zkDevJ#PuX;ecns|^uL_8M$_b=zKua2 zRVf`$eiq5_Ha5>xy42IKyMfwsT<6J+KA*CsR-o#sOAoqs7da0}&V9a<{-GXX)2DdP z_~Dw~u{?9^&bxm{c~XT8%-`@fE5ATVeb@NscGn3M*xlE;fikt~d5?A<)v7oadDphg z-!i8ORv3L5d1zNNqHFJ855Bao8P`~b`#jRpsQ`_wyQ2>6dFt_$_U9YC)f$g-mR(St z1b7@>?X{@wIB)st`#1D07QQK$v=V`?aVN8Jpoj$l2`{>X`~y>e;=MB^yY|m^!e0mU(R{D zq^?qtoRrgio5$$Phsh=G(>!nX253t1R7E`6$JK54Et+Q^Dz{U*v1|`ff0gqFpQg{x z*}p1dTxYEFTx(pPCmr&q=ehInR**u~d Date: Thu, 12 Dec 2024 17:03:44 +0000 Subject: [PATCH 147/223] Migrate C# and Unity tests to the new API (#194) ## Description of Changes Counterpart to https://github.com/clockworklabs/SpacetimeDB/pull/2033. Also updated test settings to make sure that sum type variants implemented via subclassing are shown as expected. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run against a specific SpacetimeDB branch in the testsuite, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] Describe a test for this PR that you have completed --- sdks/csharp/.github/workflows/unity-test.yml | 18 +-- .../workflows/unity-testsuite-bindings.yml | 15 +- .../examples~/quickstart/client/client.csproj | 1 + .../module_bindings/SendMessageReducer.cs | 19 --- .../client/module_bindings/SetNameReducer.cs | 19 --- .../_Globals/SpacetimeDBClient.cs | 100 ++++++++---- sdks/csharp/src/SpacetimeDBClient.cs | 8 +- ...otTests.VerifyAllTablesParsed.verified.txt | 144 +++++++++++------- sdks/csharp/tests~/SnapshotTests.cs | 12 +- sdks/csharp/tests~/VerifyInit.cs | 7 +- sdks/csharp/unity-tests~ | 2 +- 11 files changed, 188 insertions(+), 157 deletions(-) delete mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs delete mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs diff --git a/sdks/csharp/.github/workflows/unity-test.yml b/sdks/csharp/.github/workflows/unity-test.yml index 29e508867c9..6312cb929fa 100644 --- a/sdks/csharp/.github/workflows/unity-test.yml +++ b/sdks/csharp/.github/workflows/unity-test.yml @@ -11,22 +11,17 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + submodules: true - - name: Checkout submodule - run: | - git submodule init - git submodule update - cd unity-tests~ - git checkout jdetter/circle-game-testsuite # Grab the branch name from the PR description. If it's not found, master will be used instead. - name: Extract SpacetimeDB branch name or PR link from PR description id: extract-branch if: github.event_name == 'pull_request' + env: + description: ${{ github.event.pull_request.body }} run: | - description=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - ${{ github.event.pull_request.url }} | jq -r '.body') - # Check if description contains a branch name or a PR link branch_or_pr=$(echo "$description" | grep -oP '(?<=SpacetimeDB branch name:\s).+') echo "Branch or PR found: $branch_or_pr" @@ -52,8 +47,8 @@ jobs: branch_name="${{ github.head_ref }}" # Replace any reference to com.clockworklabs.spacetimedbsdk with the correct GitHub URL using the current branch sed -i "s|\"com.clockworklabs.spacetimedbsdk\":.*|\"com.clockworklabs.spacetimedbsdk\": \"https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk.git#$branch_name\",|" unity-tests~/client/Packages/manifest.json - cat unity-tests~/client/Packages/manifest.json + - name: Replace spacetimedb dependency in Cargo.toml run: | # Get the branch name from the environment variable @@ -146,4 +141,3 @@ jobs: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} - diff --git a/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml b/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml index 442abcd1f91..71a6090a8ea 100644 --- a/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml +++ b/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml @@ -11,22 +11,17 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + submodules: true - - name: Checkout submodule - run: | - git submodule init - git submodule update - cd unity-tests~ - git checkout jdetter/circle-game-testsuite # Grab the branch name from the PR description. If it's not found, master will be used instead. - name: Extract SpacetimeDB branch name or PR link from PR description id: extract-branch if: github.event_name == 'pull_request' + env: + description: ${{ github.event.pull_request.body }} run: | - description=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - ${{ github.event.pull_request.url }} | jq -r '.body') - # Check if description contains a branch name or a PR link branch_or_pr=$(echo "$description" | grep -oP '(?<=SpacetimeDB branch name:\s).+') echo "Branch or PR found: $branch_or_pr" diff --git a/sdks/csharp/examples~/quickstart/client/client.csproj b/sdks/csharp/examples~/quickstart/client/client.csproj index 93444533e4e..48917cce783 100644 --- a/sdks/csharp/examples~/quickstart/client/client.csproj +++ b/sdks/csharp/examples~/quickstart/client/client.csproj @@ -3,6 +3,7 @@ Exe net7.0 + false disable enable diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs deleted file mode 100644 index 1510667186a..00000000000 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SendMessageReducer.cs +++ /dev/null @@ -1,19 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.Types -{ - [SpacetimeDB.Type] - public partial class SendMessage : IReducerArgs - { - string IReducerArgs.ReducerName => "send_message"; - - public string Text = ""; - } -} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs deleted file mode 100644 index 83a0b7281eb..00000000000 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SetNameReducer.cs +++ /dev/null @@ -1,19 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.Types -{ - [SpacetimeDB.Type] - public partial class SetName : IReducerArgs - { - string IReducerArgs.ReducerName => "set_name"; - - public string Name = ""; - } -} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs index 726f56d0af0..031c02f02d2 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs @@ -8,6 +8,7 @@ using SpacetimeDB; using SpacetimeDB.ClientApi; using System.Collections.Generic; +using System.Runtime.Serialization; namespace SpacetimeDB.Types { @@ -25,30 +26,30 @@ internal MessageHandle() public class UserHandle : RemoteTableHandle { - private static Dictionary Identity_Index = new(16); public override void InternalInvokeValueInserted(IDatabaseRow row) { var value = (User)row; - Identity_Index[value.Identity] = value; + Identity.Cache[value.Identity] = value; } public override void InternalInvokeValueDeleted(IDatabaseRow row) { - Identity_Index.Remove(((User)row).Identity); + Identity.Cache.Remove(((User)row).Identity); } - public readonly ref struct IdentityUniqueIndex + public class IdentityUniqueIndex { + internal readonly Dictionary Cache = new(16); public User? Find(SpacetimeDB.Identity value) { - Identity_Index.TryGetValue(value, out var r); + Cache.TryGetValue(value, out var r); return r; } } - public IdentityUniqueIndex Identity => new(); + public IdentityUniqueIndex Identity = new(); internal UserHandle() { @@ -70,10 +71,10 @@ public sealed class RemoteReducers : RemoteBase public void SendMessage(string text) { - conn.InternalCallReducer(new SendMessage { Text = text }, this.SetCallReducerFlags.SendMessageFlags); + conn.InternalCallReducer(new Reducer.SendMessage(text), this.SetCallReducerFlags.SendMessageFlags); } - public bool InvokeSendMessage(EventContext ctx, SendMessage args) + public bool InvokeSendMessage(EventContext ctx, Reducer.SendMessage args) { if (OnSendMessage == null) return false; OnSendMessage( @@ -87,10 +88,10 @@ public bool InvokeSendMessage(EventContext ctx, SendMessage args) public void SetName(string name) { - conn.InternalCallReducer(new SetName { Name = name }, this.SetCallReducerFlags.SetNameFlags); + conn.InternalCallReducer(new Reducer.SetName(name), this.SetCallReducerFlags.SetNameFlags); } - public bool InvokeSetName(EventContext ctx, SetName args) + public bool InvokeSetName(EventContext ctx, Reducer.SetName args) { if (OnSetName == null) return false; OnSetName( @@ -124,14 +125,55 @@ internal EventContext(DbConnection conn, Event reducerEvent) : base(con } } - [Type] - public partial record Reducer : TaggedEnum<( - SendMessage SendMessage, - SetName SetName, - Unit StdbNone, - Unit StdbIdentityConnected, - Unit StdbIdentityDisconnected - )>; + public abstract partial class Reducer + { + private Reducer() { } + + [SpacetimeDB.Type] + [DataContract] + public partial class SendMessage : Reducer, IReducerArgs + { + [DataMember(Name = "text")] + public string Text; + + public SendMessage(string Text) + { + this.Text = Text; + } + + public SendMessage() + { + this.Text = ""; + } + + string IReducerArgs.ReducerName => "send_message"; + } + + [SpacetimeDB.Type] + [DataContract] + public partial class SetName : Reducer, IReducerArgs + { + [DataMember(Name = "name")] + public string Name; + + public SetName(string Name) + { + this.Name = Name; + } + + public SetName() + { + this.Name = ""; + } + + string IReducerArgs.ReducerName => "set_name"; + } + + public class StdbNone : Reducer {} + public class StdbIdentityConnected : Reducer {} + public class StdbIdentityDisconnected : Reducer {} + } + public class DbConnection : DbConnectionBase { public readonly RemoteTables Db = new(); @@ -150,14 +192,13 @@ public DbConnection() protected override Reducer ToReducer(TransactionUpdate update) { var encodedArgs = update.ReducerCall.Args; - return update.ReducerCall.ReducerName switch - { - "send_message" => new Reducer.SendMessage(BSATNHelpers.Decode(encodedArgs)), - "set_name" => new Reducer.SetName(BSATNHelpers.Decode(encodedArgs)), - "" => new Reducer.StdbNone(default), - "__identity_connected__" => new Reducer.StdbIdentityConnected(default), - "__identity_disconnected__" => new Reducer.StdbIdentityDisconnected(default), - "" => new Reducer.StdbNone(default), + return update.ReducerCall.ReducerName switch { + "send_message" => BSATNHelpers.Decode(encodedArgs), + "set_name" => BSATNHelpers.Decode(encodedArgs), + "" => new Reducer.StdbNone(), + "__identity_connected__" => new Reducer.StdbIdentityConnected(), + "__identity_disconnected__" => new Reducer.StdbIdentityDisconnected(), + "" => new Reducer.StdbNone(), var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } @@ -168,10 +209,9 @@ protected override IEventContext ToEventContext(Event reducerEvent) => protected override bool Dispatch(IEventContext context, Reducer reducer) { var eventContext = (EventContext)context; - return reducer switch - { - Reducer.SendMessage(var args) => Reducers.InvokeSendMessage(eventContext, args), - Reducer.SetName(var args) => Reducers.InvokeSetName(eventContext, args), + return reducer switch { + Reducer.SendMessage args => Reducers.InvokeSendMessage(eventContext, args), + Reducer.SetName args => Reducers.InvokeSetName(eventContext, args), Reducer.StdbNone or Reducer.StdbIdentityConnected or Reducer.StdbIdentityDisconnected => true, diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index c9d7d7041af..a236c49651f 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -39,7 +39,7 @@ public DbConnection Build() #if UNITY_5_3_OR_NEWER if (SpacetimeDBNetworkManager._instance != null) { - SpacetimeDBNetworkManager._instance.AddConnection(conn); + SpacetimeDBNetworkManager._instance.AddConnection(conn); } #endif return conn; @@ -177,8 +177,8 @@ protected DbConnectionBase() { if (SpacetimeDBNetworkManager._instance != null) { - SpacetimeDBNetworkManager._instance.RemoveConnection(this); - } + SpacetimeDBNetworkManager._instance.RemoveConnection(this); + } }; #endif @@ -903,7 +903,7 @@ void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) } /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("SELECT * FROM table WHERE sender = \"bob\""); - [Obsolete("This is replaced by ctx.Db.TableName.OneOffQuery(\"WHERE ...\")", false)] + [Obsolete("This is replaced by ctx.Db.TableName.RemoteQuery(\"WHERE ...\")", false)] public Task OneOffQuery(string query) where T : IDatabaseRow, new() => ((IDbConnection)this).RemoteQuery(query); diff --git a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt index e3ae0cdc908..2ab0a7db8cb 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt @@ -9,7 +9,9 @@ eventContext: { Reducers: {Scrubbed}, SetReducerFlags: {}, - Event: {}, + Event: { + $type: Event.SubscribeApplied + }, Db: {Scrubbed} }, user: { @@ -23,13 +25,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_1, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_2, CallerAddress: Guid_1, EnergyConsumed: {}, - Reducer: {} + Reducer: { + $type: Reducer.StdbIdentityConnected + } } }, Db: {Scrubbed} @@ -44,16 +51,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_2, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_1, CallerAddress: Guid_2, EnergyConsumed: {}, Reducer: { - SetName_: { - Name: A - } + $type: Reducer.SetName, + name: A } } }, @@ -73,16 +82,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_2, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_1, CallerAddress: Guid_2, EnergyConsumed: {}, Reducer: { - SetName_: { - Name: A - } + $type: Reducer.SetName, + name: A } } }, @@ -93,16 +104,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_3, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_2, CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - SendMessage_: { - Text: Hello, A! - } + $type: Reducer.SendMessage, + text: Hello, A! } } }, @@ -118,16 +131,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_3, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_2, CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - SendMessage_: { - Text: Hello, A! - } + $type: Reducer.SendMessage, + text: Hello, A! } } }, @@ -138,16 +153,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_4, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_2, CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - SetName_: { - Name: B - } + $type: Reducer.SetName, + name: B } } }, @@ -167,16 +184,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_4, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_2, CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - SetName_: { - Name: B - } + $type: Reducer.SetName, + name: B } } }, @@ -187,16 +206,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_5, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_1, CallerAddress: Guid_2, EnergyConsumed: {}, Reducer: { - SendMessage_: { - Text: Hello, B! - } + $type: Reducer.SendMessage, + text: Hello, B! } } }, @@ -212,16 +233,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_5, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_1, CallerAddress: Guid_2, EnergyConsumed: {}, Reducer: { - SendMessage_: { - Text: Hello, B! - } + $type: Reducer.SendMessage, + text: Hello, B! } } }, @@ -232,16 +255,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_6, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_2, CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - SendMessage_: { - Text: Goodbye! - } + $type: Reducer.SendMessage, + text: Goodbye! } } }, @@ -257,16 +282,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_6, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_2, CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - SendMessage_: { - Text: Goodbye! - } + $type: Reducer.SendMessage, + text: Goodbye! } } }, @@ -277,13 +304,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_7, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_2, CallerAddress: Guid_1, EnergyConsumed: {}, - Reducer: {} + Reducer: { + $type: Reducer.StdbIdentityDisconnected + } } }, Db: {Scrubbed} @@ -304,16 +336,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_8, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_1, CallerAddress: Guid_2, EnergyConsumed: {}, Reducer: { - SendMessage_: { - Text: Goodbye! - } + $type: Reducer.SendMessage, + text: Goodbye! } } }, @@ -329,16 +363,18 @@ Reducers: {Scrubbed}, SetReducerFlags: {}, Event: { + $type: Event.Reducer, ReducerEvent: { Timestamp: DateTimeOffset_8, - Status: {}, + Status: { + $type: Status.Committed + }, CallerIdentity: Identity_1, CallerAddress: Guid_2, EnergyConsumed: {}, Reducer: { - SendMessage_: { - Text: Goodbye! - } + $type: Reducer.SendMessage, + text: Goodbye! } } }, @@ -405,4 +441,4 @@ Max: type=InitialSubscription } } -} +} \ No newline at end of file diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index d293c126782..d57379b5270 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -238,27 +238,27 @@ private static ServerMessage[] SampleDump() => [ SampleTransactionUpdate( 1718487768057579, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", 1, "set_name", 4345615, 70, [SampleUserUpdate("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, "A", true, true)], - Encode(new SetName { Name = "A" }) + Encode(new Reducer.SetName { Name = "A" }) ), SampleTransactionUpdate( 1718487775346381, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", 1, "send_message", 2779615, 57, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487775346381, "Hello, A!")], - Encode(new SendMessage { Text = "Hello, A!" }) + Encode(new Reducer.SendMessage { Text = "Hello, A!" }) ), SampleTransactionUpdate( 1718487777307855, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", 2, "set_name", 4268615, 98, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, "B", true, true)], - Encode(new SetName { Name = "B" }) + Encode(new Reducer.SetName { Name = "B" }) ), SampleTransactionUpdate( 1718487783175083, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", 2, "send_message", 2677615, 40, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487783175083, "Hello, B!")], - Encode(new SendMessage { Text = "Hello, B!" }) + Encode(new Reducer.SendMessage { Text = "Hello, B!" }) ), SampleTransactionUpdate( 1718487787645364, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", 3, "send_message", 2636615, 28, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487787645364, "Goodbye!")], - Encode(new SendMessage { Text = "Goodbye!" }) + Encode(new Reducer.SendMessage { Text = "Goodbye!" }) ), SampleTransactionUpdate( 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", @@ -268,7 +268,7 @@ private static ServerMessage[] SampleDump() => [ SampleTransactionUpdate( 1718487794937841, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", 3, "send_message", 2636615, 34, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487794937841, "Goodbye!")], - Encode(new SendMessage { Text = "Goodbye!" }) + Encode(new Reducer.SendMessage { Text = "Goodbye!" }) ), ]; diff --git a/sdks/csharp/tests~/VerifyInit.cs b/sdks/csharp/tests~/VerifyInit.cs index 58d37d65965..9d8249d959e 100644 --- a/sdks/csharp/tests~/VerifyInit.cs +++ b/sdks/csharp/tests~/VerifyInit.cs @@ -1,6 +1,7 @@ namespace SpacetimeDB.Tests; using System.Runtime.CompilerServices; +using Argon; using SpacetimeDB.Types; static class VerifyInit @@ -73,13 +74,15 @@ public static void Init() Environment.SetEnvironmentVariable("DiffEngine_TargetOnLeft", "true"); VerifierSettings.AddExtraSettings(settings => + { settings.Converters.AddRange( [ new IdentityConverter(), new AddressConverter(), new NetworkRequestTrackerConverter() ] - ) - ); + ); + settings.TypeNameHandling = TypeNameHandling.Auto; + }); } } diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index 386db35877c..ca4fac76283 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit 386db35877caa84a6d8842cde1e8d1a823c7fd78 +Subproject commit ca4fac762831fe613d154a6be2f058c504ba4f0b From 844713f577a4e5469070b0ef407b3f54815a79e1 Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Fri, 13 Dec 2024 10:54:43 -0500 Subject: [PATCH 148/223] Updating unity-tests (#197) ## Description of Changes This bumps the unity-test submodule ## API No API Change ## Requires SpacetimeDB PRs No special PRs, should work with latest master of SpacetimeDB. ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing I opened up this commit of CircleGame in Unity on my own machine and ran the tests. They seemed to work fine. --- sdks/csharp/unity-tests~ | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index ca4fac76283..1cf42cc2cd0 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit ca4fac762831fe613d154a6be2f058c504ba4f0b +Subproject commit 1cf42cc2cd0b6e993dfe807b8f06ff8d3978af74 From 1a21af852652e3d550548e296fa7044b18b873e0 Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Fri, 13 Dec 2024 19:29:15 -0500 Subject: [PATCH 149/223] Bump versions --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- sdks/csharp/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index ddd2f9b3328..30db8c565ec 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -17,14 +17,14 @@ README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk 1.0.0 - 1.0.0-rc1-hotfix1 + 1.0.0-rc2 $(DefaultItemExcludes);*~/** packages - + diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 7a1c5a6e998..e93e6c3788c 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.0.0-rc1", + "version": "1.0.0-rc2", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From d8277ff8fdc575391d74bd2240a2b17744e768bc Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Fri, 13 Dec 2024 20:14:02 -0500 Subject: [PATCH 150/223] Updated DLLs I think --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 0 -> 57344 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 65536 bytes .../SpacetimeDB.BSATN.Runtime.xml | 619 ++++++++++++++++++ 3 files changed, 619 insertions(+) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll new file mode 100755 index 0000000000000000000000000000000000000000..9a42883edac922e401bd6ba877a45441258858a6 GIT binary patch literal 57344 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

    eV3KMc`FmHOd|0OsKTN= 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 RGhX{=eyz~YKmYF}@IPG@lf(c3 literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml new file mode 100755 index 00000000000..1498cec1839 --- /dev/null +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml @@ -0,0 +1,619 @@ + + + + SpacetimeDB.BSATN.Runtime + + + +

    Represents a 128-bit signed integer. + + + Initializes a new instance of the struct. + The upper 64-bits of the 128-bit value. + The lower 64-bits of the 128-bit value. + + + + + + + + + + + + + + + + + + + + + Implicitly converts a value to a 128-bit signed integer. + The value to convert. + converted to a 128-bit signed integer. + + + Represents a 256-bit signed integer. + + + Initializes a new instance of the struct. + The upper 128-bits of the 256-bit value. + The lower 128-bits of the 256-bit value. + + + + + + + + + + + + + + + + + + + + + Represents a 128-bit unsigned integer. + + + Initializes a new instance of the struct. + The upper 64-bits of the 128-bit value. + The lower 64-bits of the 128-bit value. + + + + + + + + + + + + + + + + + + Represents a 128-bit unsigned integer. + + + Initializes a new instance of the struct. + The upper 128-bits of the 256-bit value. + The lower 128-bits of the 256-bit value. + + + + + + + + + + + + + + + + + + + Convert this object to a BIG-ENDIAN hex string. + + Big endian is almost always the correct convention here. It puts the most significant bytes + of the number at the lowest indexes of the resulting string; assuming the string is printed + with low indexes to the left, this will result in the correct hex number being displayed. + + (This might be wrong if the string is printed after, say, a unicode right-to-left marker. + But, well, what can you do.) + + Similar to `Convert.ToHexString`, but that method is not available in .NET Standard + which we need to target for Unity support. + + + + + + + + Read a value of type T from the passed span, which is assumed to be in little-endian format. + The behavior of this method is independent of the endianness of the host, unlike MemoryMarshal.Read. + + + + + + + + Read a value of type T from the passed span, which is assumed to be in big-endian format. + The behavior of this method is independent of the endianness of the host, unlike MemoryMarshal.Read. + + + + + + + + Convert the passed byte array to a value of type T, optionally reversing it before performing the conversion. + If the input is not reversed, it is treated as having the native endianness of the host system. + (The endianness of the host system can be checked via System.BitConverter.IsLittleEndian.) + + + + + + + + + Convert the passed T to a little-endian byte array. + The behavior of this method is independent of the endianness of the host, unlike MemoryMarshal.Read. + + + + + + + + Convert the passed T to a big-endian byte array. + The behavior of this method is independent of the endianness of the host, unlike MemoryMarshal.Read. + + + + + + + + Convert the passed T to a byte array, and optionally reverse the array before returning it. + If the output is not reversed, it will have the native endianness of the host system. + (The endianness of the host system can be checked via System.BitConverter.IsLittleEndian.) + + + + + + + + + Convert a hex string to a byte array. + + + + + + + Read a value from a "big-endian" hex string. + All hex strings we expect to encounter are big-endian (store most significant bytes + at low indexes) so this should always be used. + + + + + + + + Create an Address from a LITTLE-ENDIAN byte array. + + If you are parsing an Address from a string, you probably want FromHexString instead, + or, failing that, FromBigEndian. + + Returns null if the resulting address is the default. + + + + + + Create an Address from a BIG-ENDIAN byte array. + + This method is the correct choice if you have converted the bytes of a hexadecimal-formatted Address + to a byte array in the following way: + + "0xb0b1b2..." + -> + [0xb0, 0xb1, 0xb2, ...] + + Returns null if the resulting address is the default. + + + + + + Create an Address from a hex string. + + + + + + + Create an Identity from a LITTLE-ENDIAN byte array. + + If you are parsing an Identity from a string, you probably want FromHexString instead, + or, failing that, FromBigEndian. + + + + + + Create an Identity from a LITTLE-ENDIAN byte array. + + If you are parsing an Identity from a string, you probably want FromHexString instead, + or, failing that, FromBigEndian. + + + + + + Create an Identity from a BIG-ENDIAN byte array. + + This method is the correct choice if you have converted the bytes of a hexadecimal-formatted `Identity` + to a byte array in the following way: + + "0xb0b1b2..." + -> + [0xb0, 0xb1, 0xb2, ...] + + + + + + Create an Identity from a hex string. + + + + + + + Indicates that an API is experimental and it may change in the future. + + + This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental + feature is used. Authors can use this attribute to ship preview features in their assemblies. + + + + + Initializes a new instance of the class, + specifying the ID that the compiler will use when reporting a use of the API the attribute applies to. + + The ID that the compiler will use when reporting a use of the API the attribute applies to. + + + + Gets the ID that the compiler will use when reporting a use of the API the attribute applies to. + + The unique diagnostic ID. + + The diagnostic ID is shown in build output for warnings and errors. + This property represents the unique ID that can be used to suppress the warnings or errors, if needed. + + + + + Gets or sets the URL for corresponding documentation. + The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID. + + The format string that represents a URL to corresponding documentation. + An example format string is https://contoso.com/obsoletion-warnings/{0}. + + + + Specifies that the method or property will ensure that the listed field and property members have not-null values. + + + + + Initializes the attribute with a field or property member. + + The field or property member that is promised to be not-null. + + + + Initializes the attribute with the list of field and property members. + + The list of field and property members that are promised to be not-null. + + + + Gets field or property member names. + + + + + Specifies that the method or property will ensure that the listed field and property + members have not-null values when returning with the specified return value condition. + + + + + Initializes the attribute with the specified return value condition and a field or property member. + + The return value condition. If the method returns this value, the associated parameter will not be null. + The field or property member that is promised to be not-null. + + + + Initializes the attribute with the specified return value condition and list of field and property members. + + The return value condition. If the method returns this value, the associated parameter will not be null. + The list of field and property members that are promised to be not-null. + + + + Gets the return value condition. + + + + + Gets field or property member names. + + + + + Specifies that this constructor sets all required members for the current type, + and callers do not need to set any required members themselves. + + + + + Specifies the syntax used in a string. + + + + + Initializes the with the identifier of the syntax used. + + The syntax identifier. + + + Initializes the with the identifier of the syntax used. + The syntax identifier. + Optional arguments associated with the specific syntax employed. + + + Gets the identifier of the syntax used. + + + Optional arguments associated with the specific syntax employed. + + + The syntax identifier for strings containing composite formats for string formatting. + + + The syntax identifier for strings containing date format specifiers. + + + The syntax identifier for strings containing date and time format specifiers. + + + The syntax identifier for strings containing format specifiers. + + + The syntax identifier for strings containing format specifiers. + + + The syntax identifier for strings containing JavaScript Object Notation (JSON). + + + The syntax identifier for strings containing numeric format specifiers. + + + The syntax identifier for strings containing regular expressions. + + + The syntax identifier for strings containing time format specifiers. + + + The syntax identifier for strings containing format specifiers. + + + The syntax identifier for strings containing URIs. + + + The syntax identifier for strings containing XML. + + + + Used to indicate a byref escapes and is not scoped. + + + + There are several cases where the C# compiler treats a as implicitly + - where the compiler does not allow the to escape the method. + + + For example: + + for instance methods. + parameters that refer to types. + parameters. + + + + This attribute is used in those instances where the should be allowed to escape. + + + Applying this attribute, in any form, has impact on consumers of the applicable API. It is necessary for + API authors to understand the lifetime implications of applying this attribute and how it may impact their users. + + + + + + An attribute that allows parameters to receive the expression of other parameters. + + + + + Initializes a new instance of the class. + + The condition parameter value. + + + + Gets the parameter name the expression is retrieved from. + + + + + Initialize the attribute to refer to the method on the type. + + The type of the builder to use to construct the collection. + The name of the method on the builder to use to construct the collection. + + must refer to a static method that accepts a single parameter of + type and returns an instance of the collection being built containing + a copy of the data from that span. In future releases of .NET, additional patterns may be supported. + + + + + Gets the type of the builder to use to construct the collection. + + + + + Gets the name of the method on the builder to use to construct the collection. + + + This should match the metadata name of the target method. + For example, this might be ".ctor" if targeting the type's constructor. + + + + + Indicates that compiler support for a particular feature is required for the location where this attribute is applied. + + + + + Creates a new instance of the type. + + The name of the feature to indicate. + + + + The name of the compiler feature. + + + + + If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand . + + + + + The used for the ref structs C# feature. + + + + + The used for the required members C# feature. + + + + + Indicates which arguments to a method involving an interpolated string handler should be passed to that handler. + + + + + Initializes a new instance of the class. + + The name of the argument that should be passed to the handler. + may be used as the name of the receiver in an instance method. + + + + Initializes a new instance of the class. + + The names of the arguments that should be passed to the handler. + may be used as the name of the receiver in an instance method. + + + + Gets the names of the arguments that should be passed to the handler. + + may be used as the name of the receiver in an instance method. + + + + Indicates the attributed type is to be used as an interpolated string handler. + + + + + Reserved to be used by the compiler for tracking metadata. + This class should not be used by developers in source code. + + + + + Used to indicate to the compiler that a method should be called + in its containing module's initializer. + + + When one or more valid methods + with this attribute are found in a compilation, the compiler will + emit a module initializer which calls each of the attributed methods. + + Certain requirements are imposed on any method targeted with this attribute: + - The method must be `static`. + - The method must be an ordinary member method, as opposed to a property accessor, constructor, local function, etc. + - The method must be parameterless. + - The method must return `void`. + - The method must not be generic or be contained in a generic type. + - The method's effective accessibility must be `internal` or `public`. + + The specification for module initializers in the .NET runtime can be found here: + https://github.com/dotnet/runtime/blob/main/docs/design/specs/Ecma-335-Augments.md#module-initializer + + + + + Specifies that a type has required members or that a member is required. + + + + + Reserved for use by a compiler for tracking metadata. + This attribute should not be used by developers in source code. + + + + + Used to indicate to the compiler that the .locals init flag should not be set in method headers. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified message. + + An optional message associated with this attribute instance. + + + + Returns the optional message associated with this attribute instance. + + + + + Returns the optional URL associated with this attribute instance. + + + + From fa2baa6cac11fd08468e2a4b955c36e359e08327 Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Thu, 12 Dec 2024 11:54:29 -0500 Subject: [PATCH 151/223] Update pull_request_template.md --- sdks/csharp/.github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/.github/pull_request_template.md b/sdks/csharp/.github/pull_request_template.md index 71d6531af42..5b1874d9ceb 100644 --- a/sdks/csharp/.github/pull_request_template.md +++ b/sdks/csharp/.github/pull_request_template.md @@ -11,7 +11,7 @@ *List any PRs here that are required for this SDK change to work* ## Testsuite -*If you would like to run against a specific SpacetimeDB branch in the testsuite, specify that here. This can be a branch name or a link to a PR.* +*If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master From a90e0f98e112588c2fb366d866bd8163433a8050 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 6 Jan 2025 20:03:19 +0000 Subject: [PATCH 152/223] Fix CI (#205) ## Description of Changes (this is a reopening of #204 which targeted wrong branch) I don't know when or why this broke (or, rather, how it worked before), but we're installing .NET 7 but packing BSATN.Runtime that multi-targets .NET Standard 2.1 + .NET 8. The latter part, as you'd expect, fails on CI. ~~This change tells `dotnet pack` to only pack for .NET Standard 2.1 since that's the one we're interested in on the client - .NET 8 support is only for C# server modules.~~ _Narrator: that didn't work out._ This change bumps .NET SDK to 8.0 because I still don't know how it worked before with .NET 7, and this seems like the more sensible solution anyway. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] Describe a test for this PR that you have completed --- sdks/csharp/.github/workflows/dotnet.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml index 643a162892d..40dbd7ab9d7 100644 --- a/sdks/csharp/.github/workflows/dotnet.yml +++ b/sdks/csharp/.github/workflows/dotnet.yml @@ -20,7 +20,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Checkout SpacetimeDB uses: actions/checkout@v4 with: @@ -29,7 +29,7 @@ jobs: - name: Setup SpacetimeDB packages working-directory: spacetimedb-csharp-sdk run: | - ( cd ../SpacetimeDB/crates/bindings-csharp/BSATN.Runtime && dotnet pack ) + dotnet pack ../SpacetimeDB/crates/bindings-csharp/BSATN.Runtime # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if From d6d78b38b9d451718d7ad621732b13a5496909b8 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Mon, 6 Jan 2025 15:11:28 -0800 Subject: [PATCH 153/223] fix(202): RemoteQuery should not SELECT * (#203) Fixes #202. Because SELECT * is ambiguous if the query is a join ## Description of Changes Bug Fix Previously `RemoteQuery` would implicitly `SELECT *`. This was wrong because you can use `RemoteQuery` to issue join queries. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: v1.0.0-rc1 ## Testing *Write instructions for a test that you performed for this PR* - [ ] Describe a test for this PR that you have completed --- sdks/csharp/src/Table.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index d3ebf918b44..56a601fa34a 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -106,7 +106,7 @@ bool IRemoteTableHandle.DeleteEntry(byte[] rowBytes) protected IEnumerable Query(Func filter) => Iter().Where(filter); public Task RemoteQuery(string query) => - conn!.RemoteQuery($"SELECT * FROM {name!} {query}"); + conn!.RemoteQuery($"SELECT {name!}.* FROM {name!} {query}"); void IRemoteTableHandle.InvokeInsert(IEventContext context, IDatabaseRow row) => OnInsert?.Invoke((EventContext)context, (Row)row); From bb6d624b6aa6c92151aa001dd34673f51aa0a2bc Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 7 Jan 2025 19:49:56 +0000 Subject: [PATCH 154/223] Update Unity tests (#207) ## Description of Changes Updates Unity tests to include fix from https://github.com/clockworklabs/SpacetimeDBCircleGame/pull/10. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] Describe a test for this PR that you have completed --- sdks/csharp/unity-tests~ | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index 1cf42cc2cd0..e9e044980da 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit 1cf42cc2cd0b6e993dfe807b8f06ff8d3978af74 +Subproject commit e9e044980da900a2f63799bb5b93cb3f91da4b01 From 006087fb430f93fff76c981b16229635ca3e5338 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 14 Jan 2025 15:28:29 +0100 Subject: [PATCH 155/223] Add delegates for events (#201) ## Description of Changes This is a requested DX improvement to make sure that IDE shows reasonable argument names instead of `arg0`...`argN`. Fixes https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/200. ## API - [x] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* Potentially breaking in obscure edge cases, if someone already had `Action<...> myCallback;` that they passed to those APIs as C# won't cast it automatically to our custom delegate type. ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run against a specific SpacetimeDB branch in the testsuite, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] `dotnet test` --- sdks/csharp/src/Event.cs | 15 ++++++++------- sdks/csharp/src/SpacetimeDBClient.cs | 12 +++++++++--- sdks/csharp/src/Table.cs | 11 +++++++---- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index b637e69857d..8a25349df91 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -41,21 +41,22 @@ public sealed class SubscriptionBuilder where EventContext : IEventContext { private readonly IDbConnection conn; - private event Action? Applied; - private event Action? Error; + public delegate void Callback(EventContext ctx); + private event Callback? Applied; + private event Callback? Error; public SubscriptionBuilder(IDbConnection conn) { this.conn = conn; } - public SubscriptionBuilder OnApplied(Action callback) + public SubscriptionBuilder OnApplied(Callback callback) { Applied += callback; return this; } - public SubscriptionBuilder OnError(Action callback) + public SubscriptionBuilder OnError(Callback callback) { Error += callback; return this; @@ -72,7 +73,7 @@ public interface ISubscriptionHandle public class SubscriptionHandle : ISubscriptionHandle where EventContext : IEventContext { - private readonly Action? onApplied; + private readonly SubscriptionBuilder.Callback? onApplied; void ISubscriptionHandle.OnApplied(IEventContext ctx) { @@ -80,7 +81,7 @@ void ISubscriptionHandle.OnApplied(IEventContext ctx) onApplied?.Invoke((EventContext)ctx); } - internal SubscriptionHandle(IDbConnection conn, Action? onApplied, Action? onError, string[] querySqls) + internal SubscriptionHandle(IDbConnection conn, SubscriptionBuilder.Callback? onApplied, SubscriptionBuilder.Callback? onError, string[] querySqls) { this.onApplied = onApplied; conn.Subscribe(this, querySqls); @@ -88,7 +89,7 @@ internal SubscriptionHandle(IDbConnection conn, Action? onApplied, public void Unsubscribe() => throw new NotImplementedException(); - public void UnsuscribeThen(Action onEnd) => throw new NotImplementedException(); + public void UnsuscribeThen(SubscriptionBuilder.Callback onEnd) => throw new NotImplementedException(); public bool IsEnded => false; public bool IsActive { get; private set; } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index a236c49651f..6720767fd5d 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -75,19 +75,25 @@ public DbConnectionBuilder WithLightMode(bool light) return this; } - public DbConnectionBuilder OnConnect(Action cb) + public delegate void ConnectCallback(DbConnection conn, Identity identity, string token); + + public DbConnectionBuilder OnConnect(ConnectCallback cb) { conn.onConnect += (identity, token) => cb.Invoke(conn, identity, token); return this; } - public DbConnectionBuilder OnConnectError(Action cb) + public delegate void ConnectErrorCallback(Exception e); + + public DbConnectionBuilder OnConnectError(ConnectErrorCallback cb) { conn.webSocket.OnConnectError += (e) => cb.Invoke(e); return this; } - public DbConnectionBuilder OnDisconnect(Action cb) + public delegate void DisconnectCallback(DbConnection conn, Exception? e); + + public DbConnectionBuilder OnDisconnect(DisconnectCallback cb) { conn.webSocket.OnClose += (e) => cb.Invoke(conn, e); return this; diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index 56a601fa34a..a0acaf37a4d 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -94,10 +94,13 @@ bool IRemoteTableHandle.DeleteEntry(byte[] rowBytes) // The function to use for decoding a type value. IDatabaseRow IRemoteTableHandle.DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); - public event Action? OnInsert; - public event Action? OnDelete; - public event Action? OnBeforeDelete; - public event Action? OnUpdate; + public delegate void RowEventHandler(EventContext context, Row row); + public event RowEventHandler? OnInsert; + public event RowEventHandler? OnDelete; + public event RowEventHandler? OnBeforeDelete; + + public delegate void UpdateEventHandler(EventContext context, Row oldRow, Row newRow); + public event UpdateEventHandler? OnUpdate; public int Count => Entries.Count; From 11896cb70b102b97068d97698bf4af57dc8ede75 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 14 Jan 2025 10:13:04 -0800 Subject: [PATCH 156/223] Bump version to RC3 and update DLLs (#210) ## Description of Changes Bump package version to `1.0.0-rc3` and do a preliminary upgrade of the DLLs. I believe the DLLs might need updating again once the BSATN.Runtime package is pushed to NuGet (because then it will be fetched from NuGet). ## API Not API breaking. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2094 ## Testsuite SpacetimeDB branch name: release/v1.0.0-rc3 ## Testing - [x] Existing CI is successful (pointed at the RC3 SpacetimeDB branch). --------- Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 +- sdks/csharp/package.json | 2 +- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 57344 -> 0 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 66048 -> 0 bytes .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 57344 -> 0 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 65536 -> 0 bytes ...{1.0.0-rc1-hotfix1.meta => 1.0.0-rc3.meta} | 0 .../analyzers.meta | 0 .../analyzers/dotnet.meta | 0 .../analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 0 -> 58368 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.0.0-rc1-hotfix1 => 1.0.0-rc3}/lib.meta | 0 .../lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 66048 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 .../SpacetimeDB.BSATN.Runtime.xml | 72 ++---------------- 17 files changed, 9 insertions(+), 69 deletions(-) delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc1-hotfix1.meta => 1.0.0-rc3.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc1-hotfix1 => 1.0.0-rc3}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc1-hotfix1 => 1.0.0-rc3}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc1-hotfix1 => 1.0.0-rc3}/analyzers/dotnet/cs.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc1-hotfix1 => 1.0.0-rc3}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc1-hotfix1 => 1.0.0-rc3}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc1-hotfix1 => 1.0.0-rc3}/lib/netstandard2.1.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc1-hotfix1 => 1.0.0-rc3}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc2 => 1.0.0-rc3}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml (90%) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 30db8c565ec..081cb2dee3d 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -17,14 +17,14 @@ README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk 1.0.0 - 1.0.0-rc2 + 1.0.0-rc3 $(DefaultItemExcludes);*~/** packages - + diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index e93e6c3788c..ce1b8f739f8 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.0.0-rc2", + "version": "1.0.0-rc3", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll deleted file mode 100755 index d90254a8922ee67bae5352ecc9ae8118877da17e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57344 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

    u^&R@zJ#sxm~W@&3)U z)TVAL&hUSYo4~&V?(_2ROY5aostj#@>i;^`;J^qE(Y6&Or*EUADpYke!dDAb>^atd;9qgPcK#xOkh zJM=eOQlqNe+vy{rc#cj7^_i-tP0F60dk5(?7=oSi-AR6-ZlUy)hTJo#jOaePBBAU)x-FsXe%g^xc0WBLl!^rp(18TW2k4M3`JjGV?gMn#rrvhl zoBJTWYE$dn`*I(m&ur?4?t{7iMPJy|qwW`SA0~YkYqpi1)Bc$Ib8-u%`g?>jg;FDW zgbHlQ-TGU(k5E~H+ki=D~4 zpYm<$3*$`R0V=ntTWOB}NvgD|sjh4NPf@E){SMS`=({#m7y^)7z1 z@hn|!Q*Ro_bDyKzZ0cLC^t>17piPy#gL#MPd7)IBFVU-Z*%j`pyq9PtE~Fg)`~#Un zZKYe>6Z8H+n_^`jx?iR%73J+5`i}buU1w7phEC6Wg>JK{L)kCjp5-B%isam<{gIv% ziccB`(qE;wg;J64HTujh+f-1J@*1V#I*jNI?b3p;(`ytIN=2#Hs9mTn#8K)sdRi!s zQV*oRPKRykFsP&Sx?PXs(wp>8p?D8CH}4p^W;>(3Fz+ooDwOKsZK{$N_o|1tX|zz> z!=-tDrl~e{7}Q^=K`1qbzfz}7aesfMD~00GuFCrxJtCBv+xO^zP--6DqeDV%#f_Pn z_a2SluU%j@w&~q@@6!~Ux?bO$_dj%@P^y&=s6{B%$_KRCmb_g%l=1;ZVr94Gd`RC^ zl=lcuipS|jn|j-KPvAJ+VN;wXd`!D+inD}|>0X=qv}7;tv>vi4-;jF(|D=6FDVzO^ zQs%PO%4YwfuuyEXEAl>}wKjDa)W4}mC}p$H=$AIdHv5bY3&l43R^I0{@_cSn?b;`( zPEpt`ZpqWM%Z1t^dz_(Nsmi>UrhG5Y(5|zoRVlkc-D*=GV0rG7Y7=DuH(XO+p!=Sv{ZlTl|{Mv*CEU9uuzg904kKyNe$=ct9x)L`I z$>}NDaiKT^{B>T6R=1Gr@%Wz1OVutCO3iJ$7FK1D#CO-U4xzT7E1{MuWxghS)`)S{Lajeuw;K158Wp5+3y&l- z{-QwD@}W}Z{26ZwHA<4c=6M)brGLp{{9@7MP%-1o(QS^x6<_tDW9>{uU7e<2Ld5n4pA6S*Pf-4_U3z~;Rt?(_rFfU1 zWSkbhBfU?TwUcO*ME=)gT`RjOSSvoDpyJGwUIs$d?>~dwFaF>g#*)~V!cWF$3pny> zrWE{kf(4X^Tq65g3<@~!lxWVlzpBOOHLP?oN#kH9b)HqWkv96GAMP3 zv>#jb&YC*4zF5O|eJWD%icqcb+a#2TofB8+skO=asOYgy)*83t_&^o3)#*fb62Ifc zy>dBjen;S@b|h{BEAf5MD%^^VqTyN%?yhR61J7~zCdVYat2+a4=%(Y&n)j?sKsUb4 z!8qO^75Hf^U$+CYS`pohD+m7qyW~s zzN2j~UhWELY&X_tovT<%he>Ib;1d8JFq$>C_B7$t3um_A3jk|fOEi8fxJ2W(f=lEU zXNku5kV`baaa^MDjo}hxc#8q~mL;mOCqy-#@r{CS6g&!<^T1)a1TFWtw`qJ2x?Kx< zzVCkAxH|uC_stsH^G=lhowjS&_}_821OL!{FQChFk+v~6%X6p3V}A&o#rj^rW%>~< z*T2wnK;t)u2egOX8v*&OeMn>u8ut%<033d!ctGP*_hI3`tDO;aCmqoE9peFw&)=`w z@*_&;g2Qhe4`_T6f6L~tPrWheEuN92J=(^UXOf;bdV)ui-jmWJ#)#6tCQUJp<)nCz zYy8ghGw?O~Oyl>BpK1K=(Iu<$h*p`i4miJo9I0&{|0$J7Y`FoKMJDb^4BL{PuOH_RErP z-y6m^OShr){*+t6`9{edz9Zn=>l>*L3qAo!esgcz5zTgp4O_fr?u+r zY3+iy3mz3bDtN2T{?;xqDsVPt@KgV6IWy0;qaUBRW+Ni~4*Z=3-sE?+b@>I!8%5h~ z0_W-5lWUR>8h=V&m%Lp#Hw$dm_GTYSzEkjSZGY}Z$=$I3GfCarrzxKTen47{26teS7q0N@k{PF)~Vil(JXncguU(e*pR9dqA{0 zB=Csg%Kr$pZWAE5J=CrY{RfV^w zHETmX=w0Jm>?u0O&v{yF5POa5q2k}94Z})&HLVKmEY>FooK1YE9ndxvj7gtn@Z8;? zwG^`56?W1K2ks8V|_ZH&q)26!hfYNFnD!br2W2hp=W`?@o)*W`p~Ume=Nyp zmC{z>w+laNNbEHv_6ojH@TeiNSKu}o7h8Kt2ENVX&!OjyFY?%cIX$j!X)D3tW-2!+geK*UC z`=H%`pU|GHEUdrXS*IbNyRM{~lEJCQd-uut)p(Cx3s_Fe04u2ta6J7Ca4J0sSVu1a zo=dL+Hqpfe)pRkf0&Jll0j{QB07mHLg7J7)o?kctupm%JJ!roU`Q@IhCU8mvEy8IL zPFOe*fm?;YRrp(RFZOid6~f2uJX*UMupqEgWOmt*+uQ}o|0%p%Bp(#X$E9??4OwPC zWO9q16qy%A<_#%5hHQ6F)-k#U@GZJbF9^IXGMdIZ8yc4y8kc5kta+L6%e4yVQ!box zZ7ZEwR4y{ZwV^aTFkbkzB3TDXSU@;+kZdZd6UipwG>c4&$g~Kj1u~ZxwTMg zk=ZITTSaCoWUepTDl*$N)_JGM>=Kz>BC|{S+9fh~3+F+={KEa<|Ga3w@Sha^ivo{n zyXf_zW5WMPIHdC!HC^nWZ>4vN44v)Z(r=>1l5Cx=5dbU*l!;6^WIit{7nxe&)PXas zxK8Jm>xAD3`TW8rfz3AL_FEu%MsbVCM8Gc%^rCl+UE0}-(({YAO6d;a?-c$n;qMau zKH)qra6kC(6zv!OQQ^EH@EG{RijN6jGh|%&$!$TvFt|s<;CVC*9%B&v{K7JkDF=T= zak=nog;NI(#wDD3;||C-8bfJFVY3ZoMACALwA=#ujm0e@-zF{eO6gV`a_?J3W~<2T zk{)*nzF%baOFR3)-&MR{_y@r$2pp8wj)9MH3EyySrQa4CE}1D8>*jN@PnP3HjRk<* zS2<)pEG`$BkuKJ@4xIdwI^ir6PK(I5hzYzfu{-Q zp!9xJ_{T)@nDE~fj^^gx4R1I8H!YLD2?iQWhtn)B8k7XESh7{IFX}#c$C@l!I zh-8aM_Dbm%l#VRiD*Ua|@($tea{n0Z>=S&ylW`$dO?!hgek6HP391GQ!sYMz^D zF(BhXkJw6Ji@>b{cM9Ak@Nq~E4?HgTeu2jXYDqWI*9x_yp>$KBk;Ltk2`m>_E3i)B zGJ(wkTLf+uxD9nj7VZ#ym%x2VZ0CJ~?-zJfI7bCPCeZL!uy1=Mj(H!Xvr5W^Q!bnu zuZ&1wvzIk*7Q98^R)ISN?v&D9s9O-&<>eXKB`rJ-{*J=^!rw3aH-vLcYLSoI*L*A= z6ueCEX5Ub{x3Cp(c%WDKy9M7T_yNJ+5J}C?bzT0Uw5+5|@L_`2__^g;;nWLfnQ)qg z(<+=Tg6|Z#TR8hf=5gU10B3c{QQ^EHoVSES$)awc*GuU#!CQgvDC`w{hrpdux>N8s z1lLko+cJT*0-FVH5x66jXKhC+_q$U#`viYn@S}piAvmRpZfP=h!OH~Jq;U&1g4YUM zCY)u0Hw)|)xJBR&fjb566L?f0rE~j1fo193OO4>Q={MnsVC>+zkCiG}sKLupINGAUgq{8sQ67q$w&S2#Nay7D;Ix$@X= zgLyn_!+@_Y=@opRK+2a<=l@pQleJ7>Zz1>VDq_nF6Id^Bo4_4KJkp~AYl<0PCa|@b z<$DF+A#k6-qXMafC2Ius3Oou3Um7ASLf}z>!BWJL6Hwisla6ddj;+g zxKH3wNahz(nT$(djlg9Bdj;+gxKH3)W$g38p)wYM`vg+Cv>>oX;4*=|0(S`9SI)Ke z34T=Yqk_{gsVlHX;Id)TzTmwAcL+QxkcNxAz#4(e1nv;HZ@Bo3;70{NDmaahS|h|y z1g{aiM(||Ez+DLti{(b$A`Uv;K?t7D7ObU5R{6Fz$ zC;utgn=(43E#*=f`BeJ#;AWV=~6|IaR>l^~GCG6%AFbbt&Ue zs-Z_dn;JNw`eA<^7Ec0915d~Az>)#;z|&#vbii`VgO1;TW@EmF1M0AK4&X>g>3FYD z09b|j(D8<$1TxitI^G1P{*&M<^q0- zUmR)pOOf+{|1UJs=`;K)NT+=5LhuU!b$sjWBH%@UIu&ad11|xDt+Y!3L)ubsMgqcO zS~KuUz#6=?84U}CFp4_#bOC-P6o%H9L$~X3(%+5u2!Ezh?R0IrW@>k9etow4Fnt_NL@xn6R;>H5^=cBi?=y3cZl-5u^L-M6?OcOP=U z<^Ie)&ePzz*mJw*Q_q=6S0^1!%JVMrc6zsa_jq6NmiX#@zwo{8^ZL8|H~PQtf5m^y z|DL}zxhnbUTgm%PCYxVDecm1mf25@HLGYgRa zolRSV{G3fM<6R|S=yQC&?s|;w#^-5#{^rWm?stDee{g?B`JTt9#B&1A z(c14lr-Of%){!(z%lCXjdz0pAZf{uI|Nh?G{e7BJJY`hpLyD5d~WxDsD+bV+M48#@cB^tF7O`#|55T;+OP0@D*1GL%JjQZ z=4pRQ8LQ`|j@PSGFVx>oZP5$U!aByFMbmE5SNY2D(b0yEx}Q*E`X{tF{U`dj(=)XX z@p)34r(KxwhQ2D}Bh=Xd`cwTa;Qz?rcxGT78F(h);|1=;(}$-IPd}dcJu_lnF7}=V z#K1ztyh7|gh4${#z*9P{uHEbmPaj6prcYVAbj;E*G_A3-E!x)H-gbF-`f{5!y=Cdr z`nJfL_U7)o_U1@LL~3%0 zv^b8j1!lvBXt*=dW_GG#;d1$S)x^rSNHlCUnO#;(cy3p8O;=Rpq*R)jpqf#CS3r6Y zPJi77WlrR}v%=8@-D|>)oh!`gE0-=!AZMD^oaT;jD;IAR+5W9g;s*LN$DS@+Hp67q zL1)-%j)v>QE7TZ;%gPIKezO$`*Gh@dF(Zp^s_KkLbF_12Te!Vd^YAmnJ?QK!i=vdQi**v8J zmIx#oEX%a&!;u!NZH?l{JkJkDy4s^CZwjLxoT9a<8$E284L9dnj^4GF)!fY;b#!#e zKpe&@@S@?4v9z$UGdg~pGx0$BPrO}*c?A}8Dn-i5Vg5;`*{M5@Wd@n>aWu25vt`*h z63Z;;S_8A=>ln&( z7$NO&HD0MZK2hEAqLba|n57d2>I9bPG>!`g=`dbCanN#b6BPp4cZvouCiSg=-#$&p zFP;+H0C}F-+SMMOj@)kA^tt%O&^q?brAujcbI0=5W~z2;X^RU>P zSB3}H;8;G8dtNxY%4{9HY-YGQ+GT}LQrOkrK6nYnfv&J^4PM;TVy+oP5e`cO)tk}P z){dAnc;Wmo)a#U`Hn3()i<6WuXkIz65>L=TZewKb8jgz1?E}jeT7xiIUD;3v%<*~Q zj^$x1GO(RmYb7FhC${$ib?T5DM6KqwK?~78_UVr1=)ih#W@|9EMBIVm5@H9iVWySg zR^DEem#*Mln3nUjh_k~vX@RNIkC~R)!L(XS4ze?(d;=Vk#jm^O*q!QaW&Qg{7^0-n0rwQQ(z3{%>hG%?s z8#~+EI>WM+C2SKEZHq$e!nWwDS@=s-&9dSnYnofaP0?-?GF9|R4|P-Gt&-G(sPWMHfH+L zrAqAuW=u8~EQGTrF@RCiDx~qk@8oeP_ni%6u@#r|la-dJCS56v?XEB`Wl9PKVNPSj z-g$(xurt!NhK~y>+qPGb%tow+le^J!JBhRBiJP9gA||F%J4|zo)3hesf`d+sPKc>$ zA*=W*oyH6y(g+~XHCC~qT@pf}XN9AQBo7G*;+n7(?N(J;tqWI$tuU$iWc5ic5_oxd z9ikvCD9e-(+QQZvvmHy88d}?sw#=~1^|F|FM~2ZO5d_ZmZpT+*4nz%zr>(8w);P!Z zZOe9+`Qf!)ZPs7{G69@}#_Kk0Xld_il?B5QqRxbx*i7RBF>E1kvN4M4!^^u?uH@Ap z=golw_T}^&TU^u`-vVB4ady2Kj?6KmYM*Od5ifwh@GjaqKb*i+p=>5^zDNyL$E9%u zK#rqw`8fBy=I-TT)-ldPU(9G+VI%PpwQmhz*S5Et>-)BWDQ+Ifjdcc>=sZcYeT!lT zMfOrih|E}`E1H^DgrnW_k#9%h9Z68Kmp(_ugd)du*y-1`h1c5)FhM{qO)=~I zaC`Fx!4k@wu(S6yNkXAxeuSCUu9j$ABd4IwT+?l}tz4B*)U>*74Nqiygohoka&l|g zX;@s;S;d(3DDwPxfwHnn8sc0Dppr_(d5sv9I$_6oaiwvB?(B{i*a-le3g%hf#>eb< z>5OhfLk_l*)e4r71(Oxei2H_fB_7+@;-bcKG{?Ci!ynM%PLVFC zT?|jAIb9ZpAPY=+v@&yMJAi%MTCfUHz7;!?!?1@~ZLdx)Q8}y}^_5*?NhJ_Fzpx9q zP^r zTe>(*K(=KynQ)ypr1&zhc*ZZoOCX!DorIB6irt(6#n)w|dhYVeaEF4m7H*FhcdWtf zW2epK0U&S^$0BOtWQvo(`We+Tnrau!!RfR$yfWNb-HOsh9qrVpvK4BSjL#u>lXY-j zhH^`n$dD{;uAH14wzy?tMaE-0zAeStshz}TL?p)(v*55H_TcAv&8x%n*T-6*sM8jS zmnk#iv~3%Knz}kL1pr|NiNm%B+=ti46tEO5j?I*3YXLIvPBhBbMhaIM**RugC)pll z-v-3PyPbou#rrV%FqXiG*&>1G97YmYbHeMzlnJbboy}Hv0v$D-{ezt}hPT_BidsGK zOE_XXCS1xvUsf%V!}H?AqT0?*lW!`_PDyINUnN?3@!`Ij5^5UI*tRT&%awMcN@+#!JqL zpigmR-ly$p5mfvRRuF>kPS_+uOdE@o9afAnlyRgiHe*7`Tv^y0OiPv88L1G9+t$!| zZ7r4=F;_%omDOUocSqVH)pbp)nyoecFD++TX4e{8DbThj(*Ctb`#aYm&sAFBWXLmR zJEYjjxhNHrD@Tp7RKjcT-lQU$LoHW#9b`t4Hmmj1ilEW9q79_X)7jy6m=xzu4%!LV zud1ggj~r=9`+(xcNMo!eSS(tH;WoD*VW61(s13(%97n<9D6Ve6xG!eGPI94(#lHqM zVcyu;m+?Wa)e?@zxMGXi2W6?4aIqXqJ4h~Q0eR{~0rk$r$)&*TccVOiqd4*rEJVG<((*u##`@9#1Hg{LxK!962Ey@$%FFT1*Ul(vRhdaxW1J2k$8Zx zJ8D{$$$Xv6uu|tI=YK-vG<(-004R|G@QY0a`Py0lRz2AyN=OVL_11=6M z{6bIyNbK5|rj5gfk5`3e`#M~~$Q^E!L>F8NlQYXQ1@L0bv!HcdRvhQ8Ot>6a{lBZ;zH zLg$nD`VunQgd*-%Hr#>5&Tcxe#JLY0Si^)O-t6X!V<3i9fo?c+srUqyQLOh zUr=plx4jZMbPhZjbL2IxZeD%PLY9@-8Md=R&WG%a1H6+)mJ*}ln|u>rz#@ah{plJ& zI4RsrZg26Y6E4Mng`gVWlOlX8dJJu%9>QN|#y6)X0H=`+WZ{1%KK1ynTLiy1v+%bJ z*WfpC%$p@;U7#r`h?+rs8FK+O(@J1xGL>BgI0qb@1RY*#9cqQaivm(l1AbYz23U*G zt&nQQcLRgyrBgT-N=^JNbtTW`$U8)fPU)u^G}j4=Ob7n6zpX+oN3B-s27ftqp+*qW zraaX+G2-MI_;z3|-YetJER{E*pJr$ghD@92TQA=uOOPpB2%REmZH?$;K{AX!f_Qd= zgV7}MC^q2FhsSI2NIFp3j&imFkBY~FdkPun3Op^ep|oOY9#5yOE0=bGYQ>ze%vhe4 zwu_C39Ky5pd3kk+FXcd!b0-{Emr?HJ;Ew8VzwNe`Z6aESxL;CWCO61v%#Wl1fOF_>iwxROO6>Fv-Gbt*q}RPrrGLIF(VI^ zG3N9)#L1Ki;&M*;%itc+&q!<4YFud#)EUUYK?Y%vE)14EV7X}23fKZuDWmb^tQV81 zN$eCOc8X*aHI;wESeeUFBLcqTiPZbJW3*PN&TbWV@3*O}3v#2yQh9M8CYOD46y7Tr?H@w$J+B>W9p6*143$>Ek@ zl=WZLgJY-uJq_&Pt3rv>e}tzuPietkJ0BlztsUc{>^PtOKfa^YOL&Owa_LQQGu|y4 zv6C#ot~t1Mt5NRkX`L8%J5fV_&dFz{1&fF0j$K@ZUT0^fOKOF~GpuGqwa)YB$OKWl z1^??3jtYCNLUAn~N#FL>Zo~NizWP1&WaEkNay&M+T{CpN5PhiNia)Mv;7`sP_=2~) z3g6tN^7A0Wdo*jt8HE#J;yWUx_sbU~hlqQI%t8^b0EfpmXIO;UtdCa^JLIH1RL0H6({|#nq6?B657P=E>*^0~I>D-DRweeqVvj0bJ zKif8YDJ_jjEBz=rUjNiAA0JD+CPvXXuUT z0}{O4Em+>^fu}TxPu~gdJEdEB=J|1%}x^;n7ZP(#H6#HyRsQA`5`Wnb-l#};%*xcC+*@JnOo#Tm``yl4W zIbsAQg+H|+J2M$K<}`#44#(3mWj%dDiAq6vDxKicS7Rp&ciQ}a^&_?Vd+-CDP52Sc z$@`6ab9@wE-FIBJzx(j2?~!9^Vk}TAG|{abEA$|rXBT(qO}4{3bYCl-%DmKKetG*{ z4%ceNe7D55pdgOIoC=*>f=531kuB~a95J0ujc02m`rzosy*VqoFONsh^AR7VGdlLu zzOrh8I6RIKPG9U>lf<_|*p8g|9*^l?t@p{tU5&O+N82H+7iW(+mG(H7S7T6{a06@~ zKR{oMpWd-I3^wnM1$yvvvBddz`0NKG@jv!m#_6;fuy5j#hg zn`F=7%Yc4~izF#CWjAW?UnWV-xtL!*+S{!aaBGPP5}%YL-Kp&BtE?->8kNSel~^xJ zTEc%y9tjsxmgJ?ft#b-O1_D{BGutN_-T0IFr&F&MBUBeJ>OuwA9TUH*PBq0-XeUjf zQU6ITn)TJvy!P0;c%5(_z9-dC&K}>5dk)n`AMZTs0uwG#*8Bmc5{A->o>wd+n^`~Bk6=u@$QqYu)?qJig^C|1NcUTY_>^UoIYZ; zPD!&y$HJ#19h;9+l6I_rYRCNxB!ciUhELSa4n??xN<4eh*psc}NP=8q9HLY{O**F) zGO!+SX~UUB{NO}W=fI;n@l$*Do|UrSw&C2$mn7=?LtX8t)8|_FO&ekq=PA{srLrG# zl;pEJ<*9s-^FnozXkyPr?vgZ8Ze(ey^3pHQskv<@qg7clXLeMsPGKAo)XAFV_-ZPC zYNKqGTRB>AK1iwY3lv-nX0im|bSN2EqBMTU?0>vuttpvbvv76>*`?|pf%A6W8@LTV z0-uqPs}FWT6F>ii`W&8lCi-ZXt}<9BtEIZcL+!x2i8^rR>(t}34BKWkkKeXQ+zVg@ z{F%!6w)OgtnJv~w7WVlv{mCs>E@{9Y&FDg(eA%pSV-ohC%s6gmzj-|N+0eo99h;vV z&&Mf={}d*&ybDL;4@m^EBQ~Q4en~kB{=qfl*&*lKqvgz04nFT+{E|cI5foX6;)|TV0y8madWZUzbBwKI%XWW#>M`9;J&e36OH}8pj z{n(6IiQg#j%T>walQ~aNBczfzKCnHKvxm|`Wx@&l%c-URnJ1=QDeJE?Xx6Ht(xKA3%cXG| zrH#ZNFKd|>sI{EfmfRR^&`K0(v6d}Gl+&<$;!so7ww8%8`ry=_T)W_RX6&Z{ECl z^JZ>lwiAYxA-?Jp3dTd7D2(|AaJV#)JQmiQ?$!~k`MI{!0_}g{V>~Q?5qP2ssWZS*m9*8d_7yk`+pp ztf*wkN`Zq=LJKv;)+-=$LW+eNRC8Fd0s@aIF1HFt`b5c6vIPAI`n)c>oGisj`e#Y{ zjU;`Z68|M7elba3f?oQZib={e135`AN&xAL_WgX3@DgRBP`q;{Pbirg1u{p1l(1># zZkB4CebZ)+K8*KthN-hSu4kJhZpDRC@=TA!jfq+qLFL)7t;|f=NqS?Xs)`dIt!8Y| z-A6cS1l63)R&%&4)W37pV)t$t>gg+G6(g5)!z1%}{bid>2 z>fWWBq-!qryFOO;zSxZt;s7+grB;8EXS1UmT zklL}p<+#jN?ea%0lVdypsOahnxkCwQX)__=Tpd@G4=veN~x4Y1?Ew_;~aN?1?-g}S&}$pa=q$sFm9d6~c}In(~pM+>h> z?VlsvwH^w!&_yAk&C88F2K26YF|q1Z&gzIptB;4V9d-#o&<#4Y&x@m!BjK4;*8`EefChS(##?C zLmKZ;Rp4qFO?yF2`Bm5A?5Qd%hw1|zMX23}s2vPjCA=_0{Y?&dt zSgexScvoF>x(F_TlPu~{C&N8}q^3ERkysP???Yu$M&#`RUy@EeeaBm$D-}h2AJ}*Y zNn!peSr6+&y;SY~R6k!s()IK|!nVr6O`>_b(8Fnmqg5w)3Fyiwxnx68Jsaj>n4-E6 ziq?frOovgAm;;k`C*O@A?ojGDO5h`KCqBo%X2o>5cLURe!a zux|M*#tho4!<_;m!|p{jRdT;^Gr4aX+P{^8kiKBd*+#nC_`_mNQbuleQ$a+x9hR!7 z&1#H|h%wZl#Hu^%tzAQC1XE>E`Vl#E`zg01n=sTQ-A>Z$@bNm;N05K)?3M@!yI4Xs zt)fLvP$f1-Hx#$!8q*3k_-QpJ3yjs&GQ=v`JSmmW_A2QQNLqJt1LCsJT1H(_V;z?& z$y!9$NPs2j;eF)21mLm?D@Y;ROX7-J;Whzpj3Ae8TdV@UPb3u4{~);ST*lk3?sDN8 z|HcHhYVCI0%Dq)A)zg=qS(MN=M=35^ED`z!zDXA!^)R+A^_ItT^kqv;l04 z&6ZfaWxCoG$ZCv0aC=sV(7jgNu>_@aG_%#*Q!Y?Ggy;G5Mpv4JoOSa?S3$Z4d^7NUAbok%AU>^Gg7givlU$>wH^xdx z`>AK2M67(11lvLvf!T`G{k>hNr*D`I!`UC+}IG*PeTS**hW^&*{2*9j;#n>6WXb3MzJO*ZgEv(M1XP%~=sUQELM zR@h@H2-+3`(3@xz%1D~9HmQN>vhK7F}6}(LpjA4 zE~Q*Z3t?*QzPA?9<`gzh##PvbkMcx+tYM_o;ljtMu}ZUAc9>*qM$g-4cQd2sf*&o@ z7;qFBE!&+oPY#I5I@V{BEQ2i~O}GxGa;VpRM!vMA6eJLqRm3M9MNF}vai0$hhHT9% z(t2VTl6&J_C=_|sSz&~>fPg- zm0JwluTO5Z$#T#Zuz%Wh@aN>VW`wjD{S5OtZduM}ZT8Bou5I4Ogpa0+zQBZ)7Ps6q z@+c{_@UuU1JpU180Qfm(*R=AhA6WSfvex9-hxMz1=xBk^`~Xf>rO>q9*MerA+f7-@ zBi)ZL>^1HyOzD_WE`5niP6x$+s~GYX28B{jZyX$O3BRl^|Cod>K@I7Am1w)l?1N<`(<>A0A9Q{Ph2G-AX|9350s z({1%8u>y4%kk}j@_?=;yYt6`2O5iXXBeD^RG`AShLkS$U?1tZ`h$fu_o@va%**HCy z_y?ennO{9%uP-UfT3m~N_N)XJ5nlmnHfG5ET^k1&#J zaE`ol>vI5Qa{vh^o3zJwASmCR@vI0Uq!;qhlJ)0EEJR-{Y~s$ImN+$H$%+yoHyd>@ z6Om1#@r8m37Vpi_)YUn(acenQk;Z^`T_ihnRH>!=aAU5%LN1$0QLPbQi@K{`CeJS9tfwG^U>?bCGcJ~`(Bg}XBBgE%eaL0AsKGt&`#j?>!@Jb3?6Hh0>AfS>XwfPChwvj_0g zj>hBN^RWCWGTLicSCUSirUPmt3}TLmo_|6oXLTMpeu5v4MtP??#}qB-;Id#i42rYU zv#dh-<1kn`dTOD=Hr)K=mW~})((wnGbe7l@YbT{GcR0$S^YEGF(<@JPmU>&>JCD25 z2hN;Z?kt`;=aVn9BTwg1+aAyzQ? z_jEfuiwg3irBjbee%y-4AU8S{Bh$?ml3n^1XHU|sa4BN8h@F!2`VEd!d7)SP; z`GX_uR$iiZ0Sq60igP;H&V5p74~)MrG||2lwTUozm-j?S{|EC>+jt*|M=9s-#P5Fn zW{Ja{dFYkYx5|UoXB~I|r@t;??c($j@wcKvVijmdVxT{^*Ln{y1~lczvfa2TKke^; zQW@X&h3FIC&I$}cOZVN3%UvSrcxt!M05N#0GK;tOQHe4(I_BEigjA;FHs6>0Ay;_| zQdHiUdcg?6dTn=YhWZ*I+FyVAPm4bY!XsZ);=kdOzRBnB^H_C_YR@d}SF=2Q z>SVuZ;Dn2>a!|q4*{4r%%*oU|hs-Q2PjR}Y&JA1MKfkO4dZx_G<_Ba=aj4gnx6f03 zXToC5`za5aumfjLo(LZK{JpbtcLtv6|N1@8v;^~$FE;*l2&cOQPjX7*xrGHg%FCyD_v4V+DZ)W||F5Ueh)+_bgJfKj zrOVg_7vAUje2JQ0mx=V(IzQvdm$nB!^BmL&iV#@sQ4i`fuS7$euY5xK@!ZMxL7=m2@=&U2 z;ur1j)5Og4yujZg{N4rD9kz(l(ZM0*I%su%FIprW*3MA3sp`G?lMZ}UhXAuWb z+o6Miij8wxZM8KvXsc+q?X2z9(4gJ4-L`h4wqoP|u6LhQ6*1v@@6Y%A&;LAMwBEDc zwbmZi+WYJ?)H%iYvo@;>FQr#dGHuS1(^&T(!7()Wpffi=y-9_sPukcXg{ieY8@iX-9Rr zf7y=a)|yn8;&k0lseeP`vs!|?I&qc%6I+*x z3V*-M*J`2&sQ0aSC8BWu!dhiOyfRO#Db2c{vMr8xo!&n1Qoj?!0!KHD5%oAeh}YGe|nxF7M$ zpY+YB6qUDFsb%*lb$Cg-{3PgPLYa#i`f)og-exM)##4tmMXOM$jXY5}%~dyV{lcXY z3W>-D+sN*&%M^!1c~VsCZf!!EV`*!fD4yju-@MIkZk|Fb&0~5eH&2S@xxFMFdjMV- z4%=zZ-E~1Jl}HWE9;-!Rp^_SUHTQWzys})Wtl+vLWS}nZ@QP^iSS>0LDizVIxuWK6 zpVucS)gjbbW{gs~{fr7@mSLg9PsN>62-C`HU0oF6M%=!m=@;VdLp-5#GAqwEwbDn2cqoNgv4zWIEdKlYjyqC)4(qesz+kWg1q%*&P`5`N z&z>q(*mS6)1o!@->~1!!)j|tvdL!}>M!#pMFQkG?`w1S>HT|(gGIRTBm5(|cao? z(Q=5zJ*H0Gc9yG^L{dAWY?eEKnZ}NwEnZOeVp0V*uhD_1rdMH76?QDBM~YZ~866%&e z6M}?!BUnDn)JpRXF*F;h-p3xMnlF_EO|5j+A=1m8L{bO3&N282^+$eE{o>_LD%L+H zTdkB%hGxRRsfG3qpIZ{Jom(QU7AUMa4kHr6Uig#d))}a~#oY4S#buhb+B|*El)l{^ z!o0@xk(@+NNK7BAm9A3D=_6g~CDTWQ5R1$7NmO8y8pZKbrca^@J0#S*(+7)}Odl*{ zoIcH4Q8$l)%pWi3PX}oi^GCKae`ZO??YeW#kLHg!IUHBJ?pQA4&@hxyCu(Wbv$J$^Kv(g8c3BCQrElzrMC!b%06^^F}Ar?<82Z=-+z8oaNPhJi%STdeCzHmI7x1vrSPn^DB zJ?JRyVmxIl40e z-<2p5`>u3_V=Y36#S{B(A~lEayNN_J@4J_oP>Mu?9kXX>7y_&QOh)V_4IWPnptgb@7-%4Q{bI;`4GMY*`? zBiS8?)q&{@qD8CfWNOy46*tj1q3>C9ooEJ_P+k(Ll^Q}gDT{Y?V{%t-wOyTvxC~vR zI1RytqO-iXxvL_C=qFuGcskY}$9#WTpVv#o3sK3rcTIndj$n&R-uU@O82QzbU(_ep z5MRpvgi=4chQOiyNY@a^N=RIICGm4NmZU3*EfSGjN#Gh_viQmMgY+&+3yMdlheOvc^rWz`%g zcvNov%ad2DJXM1p(kYca{D<7CtxZQ^QFMwGs}2y zaJ)B&hqrKs-)q)a4ftCj5-ryf#qi65U*~||kwq*!)ptXtw{z#S(q{O5g;={%;r*Gn z%!}P9TZeF{^mq0zm|53f_N-~E&b8ds3O_4!p2RTDtU3wI2^~OZtm8PVv2LNSq?4@f z{O0NgNOdDov#AyFtWcF(Q#er*ea5Y##=6;>=tYYu`?}=T-G3L0pX|R9 zN0gQy?Y~j+k-fd<4Jj$rFA>$qP@yb?xTEEbNo>vgC3aMmjrkHPf*GeF=1>9l;SSNa zP+AtN4w!pG;gch4RW)kzduwX2NzYcPj_bP&+#6jE%=joTwU;+Fidy|2dV6`jR`Qi8 z-4T7p3@+*>hg*@osz+Zdcfh>GDO0O$xJ|q*-T7~th__MLHPJ?>kCo*-p+XwQ-|Mo| zaqTi(H9{AnyS>YJH=}yG%m=CyZqbY25V{ypvjT95DZ4CTbfTAtwHC0A6|aPZLxv|L zf^DDM|IE2`6}H`a7k0li2H}u*HLwOpRDZXaSfcIZ;KY3y^HBxxzY|>pL+|`c z*J6V)Lf)~sbcn74Et4||X*N~LII1_w1f`6JE$1E5(aYgxS+7JD9=DDwqz;skIW239 zlx^A0mGBAuR;E**5PW*Zq#r0GWqL{3L?7E`D9d&814)KbhxfTvb>TioSf7D;GmvypfEbHQU*plQ+%iLFa=s#}EN}@iD;4dc-m4AFuZ(jKMf*L-wuK z#{d@?$zyO@Gi_@OCc0yAdvpAEv>pE<*Z0n5-@DrOT`9hcJ0Gg~Iec(G^?a-eb@d`U zb(^Iak2zy7kBVe2dqN$sTzSb0DEO6cTc3bC-XTW}h^G3=0aMaZv zbs^u_@w~kT@^i0Tz*CChQTH+z^ebSVi`$s!VVOCQdujYAMO}rlX1ZuXs_25hs^$-tv?~m70 z60fIAyq*_Y)PoiRHNSA{!RaXKAs+JXh}TnU>yce<20TpYC8?y(>o{#l>~dmhzU_l6 z%GUO|()f=+ zsG9e=*HF8=zCDg^@eYtD`UFI~zA0FrO5E&p*k zSG1naUooB1>nQe9H=PWP1=>nyqL@?5!dOM(>8x#$PI0IcU^=C*lbFu4po-7i3CZac z3)4xV)pWzxgLE?&gV_w zE%JGb1o`89KEwGb-Hu|>cIPK!V}Z8vnJDJevM>%i@%ee1G?kQ3aj0WvWOtXo+I-GT z&gbdL`4kKDNukwz-X4$tf0obY^F}%TwXy5t2;+Vgf$rXk?s8qlLCo-}mE?8xZdh9+ z`W}h?$BD*qAM2{b6K#wqnnANbTZv8-b8KN86XS`#Pnt?fwA5b5l*#RN>G^8uH5Y?( zl9N3tIoV=ivMIE-wmuh6$WhPr%kiqw;~nU6+qr%O))u+`r6i!OTuV4fxn|5PaO7M| zF{hS=lXLxqG?kQVai|mEd870^k?UDd#}^8mTPIE!#KK%tXf4-&j3?x%=Xy`PYUCQ1 zc1Or{BdjfQy-O0%R<0$Sq+By*7C3UQrI=I8!pXUQQJPB1wK&uXFxS%aM6PE;9nbaT zsQd@w&(TlVQrD?HzfgWDcdag_3RU_AbL66(c_1|G_k?Sud0d3`4!b!?CV`hOP=UR$6wJiL6(y{Sh z(o|Be#i34sxt5+May=L7c&?`<=UObxHHFr4T^>)!QP1_zc-6=?uECFx>+fN0k!$&e zvCUjdI7zu?%q(!^TuU*hmW7jZZKSEBT#G}U0CO!pPvp81>UgfFC+Au$%r%A9a(!w% zAxAyeljBt**Iv0bAomJ8p?^O*=SzpRMXs}tlxqnmDc6jd1&*9+DdyC&aB{8#Epjam zbpp(_^gNMkd`X(fHSSd;&O^k)TvKQ**Ol>v9Q9mZ5U(1!&PR{i&UJfOTjaWvB%rM| zM8ZkRHDhLhBj;L*IkhaDoa@F&xJakYh0)&axE6-nnG*2zA2uNqn_(K<5eTq<>+zSxgG>-i(C(r1hkcF2`4Gn zjF|IsxWddY;Jjc~Hl5jf?n1uEoM!Q)n&M55*I5)N}o- zc-6@DNc6bvT%QbUi(H>731}8UC88ZtUIoDFmsb%5hT#uKgl5#B$bpp(_^gNO4 z^P!IC8rSiOT#JRdrqEihcgGWQ)N}oIylUin5_;TruBXA;BG+e00@}*8gp-tO#>@go z&b1VCYFRir*E6N5q+E+bod9z!Jx}Di3hH>SaUGw?wOE*I3a#b(&+&vD^;~}$uNt|I zpvP_JdOoZza$O|}Xe-wePP8$8?};(9z>#w;#hh9ePR{iO(o|Be#i34sxt5+Ma*eOX z61m28d?MFkVXi5(mTSlJf9|?5UNv$ZMUUIg^)gsnFFMv8euW=op$hBCQYYMI9x@go&b1VCYFRir*H=kXNx2q>IsxWddTw(q`71O^mEb<| zs)bTl=r`E6(o;v{&a%7(s5;=&AD@%)!Oo^?@VN?~pW}lse${S#_TcjkKABpnQhbib zXDmK5@rmMd89p2F8H6W6)T%{n#=-Se&1|_G9CWK_7gM_vjq|%${~#%}Dw@#BgChPx z_!3U7T0-qLh=Nbp_ycx3 zd8o_ZGrhVT^Sovk#^Mrw*N*4bJxX=K9PuodFHv*z0(rf%0(p3DU=gAmg!>!Hvs}Ip z%*_wv!-7WyqASJn1ugQ;R&GI{0G0xL<$sM>{y~d;N0VC^D1@aj=tO@emd|OCFBNi& z0!6SC1@W+zSa2@}?Z_?g+;)L>u(S)NM4wDplf~8Z?A9av5 zx7Tu6oZC6j8J5n$^k`5lHd48W%PkHR!%`f~h?a=OW=AeLa!Udwu#^Ndqu3*xGb$&@ zxm^NXVCfRfik>8ve=-MhI+t4-D21gom>r!U7ThaBcI4zEw`-s)EM0>+(R0LtuEQdS z%G_>&Zm@I<2BHhaf=LRCEbO`61KnZi9t=kDC7*ZD*R;qolzVL8*ufpKNCb`z=0>k> zuFx(Q1)&!(P3%7H4SA5GGHWQb2JY6Wp%>xg8j7red$upx(9RmTbEny7{cTn4t%3V@ zz!U0`XrzO+a32q(BwIRK3-|MYH`#KGwQye#q$XQBSqt~~fG^q7InA25(+AQHGx@EF zdw#%wm?_M(06W4%1#$l#RYvMu>$UMxHWldZV0$GQdvaN{=Lm>MwQ;s!p zfe7RrW(rsn7m7gOFjLT)xL^c=hnaG%i3>*{*P0T~$&_NI)I5M`BG1WSO~Z33#6#W( zp|sD*bhXc=^r`tRCPoYuC4SxDyTmj3^0bQo(w6~A58A&1T7#nw9<&#W{O&@}PhR?|UV8c+u}QQsLq>1lC3^&W~G;n^RYxP-)o z@5Iz&=v$l)ZH0=bp6Jp0;wSIKNS~s##Ls)0-)Z|meE3exJyKGt|D&i-yr*m*k3Vqw zG`I;$P>y=7(uZ@s%8xTf@C7 zl!DbTQHL}l4zldJ4*zv{FN&(=nHZi}weHZa8teZOo@2QVhj+7E`|8`pL6&3J0jE^S zedtgvU$yhht96Ht)qfNRS)5yUIHvj^;vj2u>kgf&<(oL3nzioGIjvg0KjLXx8y@~@ z`PPG{Y;Aa?SIfP6p1!r=kx?yon0YGKhDT<#+!y6(T^k-*)p9qFXL)USWLL{QD4z7S z;gM4s3kXOs!aW{YIg+>o{UD%Z!h zo$EC0!S*2|Tq`%C$ILYjVn5FH3$V7x^~+GTlIuOpwS*J>Q#{v(loSWT-zIkhjhrDkgYi zsbfdM76U&Z{v#Jg=ZZ7_a5&Y|e|~p*S|^b2bh*4xBCSh&(iW1TkO_4?K2sng$1>h( zp@-MM3i;#vEfcZD?G%-Y&xQC%9rD46h&(6Gcel_q{+`IO(RtOYnTztg>WeJFVd;f= z+3LDH9Q)Oq>DOg@)w@}*1-xo^hF}-Uf2DjHv5J^ReQmn<-0m0ri(hKMGXb8xaz*}|Z%xpv zPG@EwEE3HGqG7L|r_Z*0Y4-qoa&b_ys#wq3Y{^E)pjfNf^W&+H6iPjRMGZ2(Q!!Iy z>@muCIqjGJ{QMDdb~+*wCbKR_#gNw#kTI3OE=Ima;5WrEdBJ{>d0qAhSkN}u^%-LG z%CC-qb*5*k{B8i)Z!zK{@H;7J9BeA<%#`;az=qH>3vXz}!14+g<;}sb2w)z9o#Wap zOLbX0+8$whS@ISVJWphuS#swO>~EM!BT!36GLs=JM-`LxCkv=j>zOIGT$%eQcUzWa z*n7a9Wi2Im&sc*!oIcBpz&*#_YBlQe>RDzESRa)JTTe5~ECL%$mPghV?|O)>AK9^3 zF@?1wD^pdB_R$=vrMJ46w$ehWMd}yNhWupqyCPwI)OBqATiAxHzS#4nFQ>9Eebv1z z=gnQ7vq<$*kCPoB>#v?7dyi~@dRA>lx$A=qFv#WVH?&PGT!0qJ)lQ6kj(R(7fw=^4 zO20_Y%kg6hxI?PmBKuZZ_CCvHXeoER`jG4~mo<@XBRfIuBYQtbJO`=2kc}{weMWYW zo`clqWV2oNCD}(VJ3zM1W6OO**3PZvJF?*}`w!VSZaJkTpJ%(wA^X5(Ub2;LooQrw zZY>#P(_PPOvUgk-)IQXCjmz?Bdy#CgYDac=k@RzjI)?1SY+*xH3E6Y>9ICo%KWd2~ zw~N#;6*`RdJdE|x2A+?lDYX`!{mHJz?zC2&h@Ue})G}O6OkyXg$w@4%rYErx$Vdtn zfWm-M+wuDZvsvfTY^Cbe43}lWR>UOgC z(X)EodB2}*IO3~Uv(&H1Mv%=`FOlI~4z`GTm+TYH6A<9@B)sGd#g*(UWGYmxJTIan9|V7jaK z@}BW`SF5rcfzJd!_m!y8sXP7ny3yrD?sYRZ+w zb~&PX8#p<(FkAXuk^2T({~`EBlICq{-cHiA?Ng%8&KCc(v)>2irWU6huO9OKm*1=Y zp8W=JM4sUGw4K1W)BfZ?UX>R9$=_f7%#89j;||K-_`dK;*+0W7a*3MkU7Av&Zu9;P znw92De>v*>8aN_PaC_Q8;M-~5bg%burx9^2%}!6B7Rw3<{<1*u!6LyAseeC5c6;E`?5@D9Ko8(A3j`l5@&Z51 zJ|6gfj^J=3ID+_%7Wp9YY~pO<2gHwvJ?Ytxm`7|!oKEXIz~j{$?#cR;VYD>yX06?Dh+v9vJ8 z=<1v>GB(*e8hD#`9QwaJdm`|$v@?NM=ge|zIK3D$wd5%u-Ep+kId^#My)CIV!)4 z&DntLC-564$GA+&;g7+))nOAjI zW65OpyprBook_OFH#qlJtgdrh_Ek{WLb6ZwdBNAQk8O>!x6`|*m&i8xP6+%ly;K!- zmF743LSWt0`If0U*?ZHERm;d$t1*T9(?jY>GMkBz`p_-sEBps+U%Q@?mmca{*Vb6{ z$MiCl(#^Ke0M<)olf9@UFMZS?mq}jwsME%KTTbE|sXEH-3Y_(w7wnQzp-v)`_(B<@l>Dx^jW3ijM%9zq zh)z-a$ZSNXs1)3gQaCG}?y=*#LGHzTJ}+Y(z6vxyvM?nd($BiD*>D zIZA#u7kyD%1LHDgsk>ZO5vcM+)PpX&2yBjehU^A)&@(AxuKK~XRR(5d%v0IDY%Mo| zovS*M-JqVxJ2&HeHN&<2tSFjsf!gGoI&A3FBxojO+ts3UC zr?Q{QSgFR6*?!ikX=Jvab?Qv(iGDtxajBZ`vIel2in`^bpO>lCE|Y#uT%r2A ztO4vQHJZ%MtZUSGmq}l)QD>8Vietd%8P}?L)`p(x%X=w<_+p$%TOoo!>L9x8{ds8 zqo1_Ci$}E^)c`VyZ&=DrYPid==cH^@XOP+WZc()^llX2?S6POLCZyad72;2hYCSS< zQ_s;R5tV2DOub2Vx%zd%@XXuQ9x@rD(V2JHN73{R%AYbm^DY(YFSUHCpYu)4tXEUW zZYcUgZr_y6Y8si$v$Hcdt18RX?Y_C0cdJ!yxw5?T!ESWfae2|qEoxi5+=ZE2)syjZ zb(!1L%Sq+7sSlIN-6I{r--{{5{xzBRs(-|5*_e5s`XQ;@{i<|;cz&v-yOdy5?%~YGR99<5uK$(UpvqlOt-j0rr5Z{mV>B%5aW#s}=K2Y#9)B;U zNInxx;(Jofpywv6d=**0QY&5dP~K@-PpPIjo0aj5tpv3k^sG<$b)0SVZ%TPK&fZ9y z>TOh`28!Yab&h|3%Jb?bvQM>?`;BUFnUve9UUiw2dqEvY@_bQ+j+0tG)#CY*n&&d{ zd_`SNX5-tfZgp)3J=3ywtJmY@DzjcydB@vYq}=b+5Heft_iBu5JLp-O^?NnJWgGn$ zXT7dwB$azZ)xhCOp6{ri$33sldRN^W_uQ2Ao_aXR^8>Xz?s-?% zAJv<2&uv*Bst=PqKT_YsJs-&WSp5+9Y{+U-z7rDh{YiCo*+I`US$owemu>X#%G#$Q zNuHmom2uD4vi_{@i+jGE^%wPFlILI5H*wF8vOZHk#63UB`kV3%O0@pDDs|aG&)>8D zp?bP(qyIqG7iwUV=ReiNxaap-|5DTAo=)}w6-n~^TGhrq)3d)(YvP{4?0>6klRUpu z_r*QiXCG8A#XY-Zf3Nl>c^*=@d5u4rkv+42P`zBX(O;gebi`#cUyQDedk)KX^qRP5 zMYcy@o8;-$_r^U>%}&)1#XZl+_UR{+JpKC3xM$bYbp1u#vwv!ao-!nn&n$fjnVqfK z`f}HH(9_wMt#5VNM*mH|9DPqxxuAY5sa&r9WxU*3*|~aWyxiREJpEo$xdQ#~q;iG& zyLh<^vI})!sO{NCe|2_|?&UJcQhR-}%MN-j$?l-fjC)>@-BF*H7kC6QwSN1^tU#_Q|T^y%B zA(LayzU<@mcVu!b{w(_h?HewAk%%tL9Ha}$Y(#@~skQmOcj__+>z*$2d;XO@SPvw# z5e?BXTaHJrA^H_EiRk<6q52({HGrL{|LT^LbGMUp+DX#7y-Gew7n0eC!n)WpMC8pG zp~t$O646LKiA*BO%&E}ll1W5)IivJ4x7b;-Ezk0)56l;r&>ny6n!_D zompe`Rx;Vc`{s<*J6yKWKPYFMe$r)9?liqWsoZ$|S-jlHobmc!@p7l;OwekC!k=yL zblsoKwl_(ayS9U#sX3GMP?v4=&&oMNpORE=ie8aaZmO;&lM&Nus=k`cj@UH4$=ZBx zI1@b6^j$9dqjP@FG<_eL9kJ>9fGx)no34kClzz&HMRR88aV~2BJ4??ZbFZCroy%kn z&eYeC$%y?c^BjG%Wf-v)IkWVyT~9gJn5|zRlM##MMDzz_GGbTc%+dQSgYCMUx%yvZ zHlj-XgSGj3c{b)$>eLG9=jFcRJa>TQklBdl>6v79ubQW?Bjedq&U}5F%W(FTbDn;{ zEhlrZO26tdiKt3{KxQLap!Zsah#t7e=jPDXray{lZc+kS)_ZANkq@)EY{_g zF`}p*NoFHjq9<6JZ#W`aqNlm+R7A8yN62hMOZ5(0j$^b`{}-7=^xK?jz29XGV9WG> z+;Y5f(;Y|Keo90a>M}AL(M7u4GDP%;oQw5L*Ha=|q34lFMDOKXqF0dFh-&p3%U~Op zwNl?mW+ST8cUhZnhUep)I(?7JDm|ZoJxpdJx>SE}%Q2!$b?-6KPl@RBoK+xiE)~(SCT_zE&(U*|fh}P;gmLZ~l=d9B^Tu+JUa@{~C5&e*Jg?^b#BJu{V)Nfh_ zTUOvI{UHuwBf4Af zu#6FH(NB}vh_>qATAObZ#%Qblz02;x7;V+>k=cm0>8|4>20KRE^kOoJXhz^3eTmB& z!0yxQ$!tXT>jzvW5#6t!CbJR!LhrH+5zP(k(0_M5C87uPS7Z`VRp3GGKUG?{5j~`f zEMr6u>to4mM33llYxCWMh#t{HUG^X%dPI*Rvk^V2H`sC zQh(=`la=8K-R?B$%ZpgA(^8($$CBBIp49y;LqwMZex=WJJtd;2^c*sYXm#LeeIc2R z=o!7%GDh@keG{3D=vn=9Yx8wMM9=DbUDgv3J*yukvk^U~zqjQW(Q|stcI((7C%5$)19k=ck|(05pdh;9tLs9$hBC8FQz*T^KI+X64?Katsp zUe;e&#)w|gKakmocI)&B(zDBb0};_~o$Im_5z%hlk<3Q)sy?60&bn9iqhu0Mec(0y ztjij}ey`tf%gGr1L4WBoiRcgd2QnMc8`?KfT9-Q~_Xpn8{mJag@RlA-CJ{Xncw0{( zvk|?cXIjRH-qjb7*@)iL7g?L{C6gC;Pp@*>A51&2E6Hp`@9Vd0IgZi$y3^^>7m4V} zzz4d_Wes2->fvN|j6TxmxJ)AYNMAr^Bl=h`vkVdaCeWnsbUkH^_ULV764A?nKk28) zY(#tYOO`RBefnK88__3vueJF;Kt!MD&s??_5q+W$klBbn)!|7JgB_z!_0?n&(d&Uf z>rF0e0NbzcC$kZKreAiMMD&?{m&``=H{E0zBKjckcb#^Iv|z{Ra~&X)i1q~jp}UjW zh`!JREn`Gq>IyO&(LeP>Yx5mKME}&&U6zVj_fH)mvl0DE@37@KM*q@ZlSxE>2^`R7 zvh+pniT@?=wJspD5&c^q=Q4@t-@1a#M)a*d%`!yv&%k$jx$7xobWqokNkrcUzSlRB z*@*t5>n&qMhx9{aHliQ&)7Iw8!G83E-s!S-i0B9XDw&N)nW8DuYdc2D%q5eE6kgO> z?6L+h$6Q8cBT6xwT_zEwn1{%0L|*fxWr)ZhOf`F4Pl?E9_LE6Ofnb_BL}nxM8+;*w zKRNftQwpX7nT;sJ9BXa9#fT`w^mWp}E*H zMpR_3AhQv*GdEeA?=nQx&fM;@YY|a9vz5$7)ZTny%Q2$%X2^8ur$p2**uji(Sp(QH z<}5NhMxD(Hm&q7)Hdm0@h>Fby%Mj6!V2Sya>nRa+G0&4pL?eQw<{dH{QCG9iGDg(R z{EN&+)ZP4GZN4#xsJls>A^p7EcRC{KZgR+MM8}$$WOmjaYwjVFh)xNH%%d)A04p;u zy5(eydYMmLCK2^A|01&y^)}yIhKSAx_A%Ygl-BLa(AV@PlZeg?_A?{NY()Ld>6S5~ z0cJLtji}sQU~Rs$5K+0QaoIdXRBl$1*@y<3muxwX(LfVCOInwRBEjQKCzmyVonQu# z*)bYyCb>)^8f<2h*@%Xi^DRR}3xY$<4X&q*(J*rxnMAZSc%pfb%tkcaJYyLnI?3!N zvk`^OyVmA=9BW+ZbHGqvWcahnM z#+YBbOd=X%c9YqNPBw2@hKMc;o?`yvdP+oN4ZbYIpG0(3aGYsRW+OV4|7c6|%5a)F zfi@e_cvE3LeSbqlbBdlY5z}$Lw6`bit-_sPT`kiu7l>z1*OpWC5^RH9 z+qB%b%p7xt%Wls7$jmj@li4w-;}saM&*3dmrO?Ggb=FvDuYmi<(!HY*EwwJn6NqbBXCkX6syH{!-O! z`*(1u`G(A9soFRTXv00uAA;2;-DNL1DY?}qkId$*#ze^MzFA}LCzG6I5HtN9|vnqe=-@r&bcei z7&4j3-E-^A6w6@ilY6PDB(o8%GEr;8JxgV&+v_jg_mz#x_VHQlty~1pCJtd+m&7EWt(bU|l z%%fxy(ahYdO`}`xpl4q0H70M7^hNf~MY-3Sl`fNgbG>O>8+kIO7OnoLM{RqR zT*Lpap4T|%Z(@u;z4af@(iKVj$WN`OIb#!Y4Dw)WNS?{bvfVpuZ=dIW)Qx+@u7Kn) zS<@TiqSb?l%c#AKF4_7eH9xh7t?iG=wOP5AdwTMIm+&#}x^Wl#Y<*g{HfN)CYjTW- z*ZF__ZEpW>9*&%cSDnNW(_E>-qChs?FAuev~4$^&E4QYP0pMJW93MdNv%T+H5^jj#6#5p7W1VZML4B zM`?!GdcHkMwb^>wI_}7CC)jgHd27r)wLfh0)34@Q9`&SVTmO&o|BuJ$g`OgL^9yfP zwNoqbk$3Wg_^iOE0B_{C$7cmTo$x+>7kpOW(;e^r^ijolZ@ff}g!Wv#kG}xFYPJ=> z7`7E}<8M_Vbt!(C;sd;W|AFd_Ut8#-{)9K)KUMwIU-8?XpQ{1tpQ>Datp=*^@Sgf1 z)MWGtcrSmD^6SAWOAo=|V#7%ME=C1v8HIPW zN2@XTZyX+cn4nHki`7_F4R)bAOS{GntyibxIrB+)cj657Gc{S=gsA=kcHC;W3_og3JXX4HKv+z#v*?7x-Cf=<-2X}C0saNo?O#V(q)EjE9>aORi zx3TSl?H{mx4R1A1!!H7yg$&HXEugt7P06!Q0ifh{cdj4z6XpH7{=~t=5yY{?NyIaW zbBI;MrNDgTTk5$1*a2?_i@crqD`1J*Pr1L|oqMCY3iyb*O^?Ps$<12sMUFCki*}mL z`Y*WmxLNnbJ;&3`W4PD2T|b6 z9W68RCfPD0Z;7omp~9)+gEtpen&*7;oXx7CXaPK>wmqmhU#&H}b5}Y0^%HrQJJ;fO z=(adt>M4N+N5lGrb2DqWnPqQAoo_jJ(0?oSTdChl{SN9Ih~MfRMV&og>U*>MdtTO? zeJ6OHF|@RQnAIMpB&RPl@?L~w_;|?jKEpoLJOLXY*8Qoc9xH2U{Oo-IGX)(^0U2iU^{?3?Jb zQqs)3ML$nj!O<@PK9jP8Po%FvZg-|k(kkU8e3LQ}?|{CnuPXR`$_Vs4AHR!Gl>H8@ z+X_BN@i_7vyyWeRloFKvDkZ}y#yh$hj=Z&-fj91oym`*<+}_@Hx?|u8)6tRlu^afj zy!f9ES^C+)CmnmyIuQQ*Jp-Kyc*k;}6UyFc+UXzk8ue7_>nYy^`A-_}6heOo zmy+d4G7A zBX1Oct4}G)N*(3M+vBG>^2Ycm=b)!6G#mZ>fpY({o!*vrQmV9a&@ z3VbeaQtA|z`c_XXnv*)yk^N<+BYVnBM`rsxYUWWhkD5uGbqlFqNc}?Umr=8fnq}0i zq-G^GE2&va&01>KQgbbOyFTS+U}xVP)SRQPMb9@uBhOc7AYQMUr0>Yv4q4u^&cGi0 zwC@g%+PC__f>(XR9C_oq%Ix-h30dB_9_Gj!*TWonzj~M>?^h3VNmi4r+E#)4*67*#9gXQ)Z@R z;YhL+I7Mv$&QK2lXR23$5w#yUPaOiDuX6oa_?4xOz$NMg;4(E5c(IxdT&Y$9V``1x zhu?p=8n{7S54?l&eUMXBj=mX~r#AtM^sT^-`e(pmeFw0sz6%)A^}t^GZeTyX6*y4e z101C90}j*o1H*a;aFl)!c#3`)c$$6`c)D%?PSKA8XXqz^GxbxzQ;f8Gn%U&Mh`8wFh{% zD#`DIqtyW51!@xh!F8#*0>7_)Lw*I0|2O1UQm%C6TJ=tT4SY7`F9TMlucmd4i{igV z)vEvGZ>DC8i=y8Geb<8Lso9D1gH8E6+15_zPc7J~*1+dYYWC1)FMKM~_foSLK6488 z(&qrqKC04{mL6)Nqs7zF(sM`Gsw)fd4g;*kw3ZM{=~GIdQuy3eP)eV!`WkqaL%%6M zOwSR-3i?;jzXJYq3M%M7mY$QTuY~@Ef=cRZs9y%GOpmdKHTov?w}Lga-bDY+)Netl zuL`zMzm=^&#mfWp0OYcKsjq33?xUhU4; zMzZ9XT6IdHVNQQ!XKv8p&iSeM(X4)Pho$>S`oQ-KZ}ohUq_o zSiw>i)K{R?tilSG8g1IEOVT6snM16kXC*x==~+q7`P8h2|L*+N^jrh$y23TIu4U_M zX^HN-X4tfl`tYOVrSreDQUH&Ihh zc`JOX(zj8woj%*Ce+=@b{6_RpQ2MZwb?&173-o`J*hHTu`s`&yd#T?`|4%6I2Ue!< zr;p=d)E@3H9*H!Ca;ayFDk&6Dz5ybY-b?KIJO< zuc37fHETQz^bPszDA&`vh1M<9Y@u}<viPK=NW7)cSEhG^enWZ>Xb@Kl<04kjI-1r9HI*rh1)59JtLR@v{Th0% zVV!H}vyMJnC~sp8+v&fZ{*A<)EVYxRcGB|&%1yNHA?~HmUh4PK=M&2Nffzyh;71OT zVaLmH^l}`%97oEuKH0Qd{V=h59Y@*+zLgt=s9@NZd)!owV+x z=L?jZXx&5qz4X~j{a*TfLU})}`|0VVGGnRCSSm9{xg=HQLn*DL)RfZNjdBklGL|Yi zub@u_^%e9PO?eJ$sHC-$no3&dQ?3FcOROOVpH2CzDX*db8v3lE|2oQ>Y28BW7HYQ8 zx{dO7U}gGt`s}37PU?5k=LO1pso(3$66q(D_X9DDSl00|8$M>k$81n8@yW=R(ppMQ zDXrZo_W&XrKJGR2sc=#1si5a*dRDq9HP5G9#j;f_8zZiveho{lqg+q@7Sy>Ze+xC+ zh}(gPn$||*PWtSm^#x)R^?NDrWu2c;-Va37w5l}jJ86tMjZsrBroNPNDfQhbSGXvi zqbXOWbwQ-_(>VX3!N{`g8d}#8ucH1c>g(Z;Sb&x3TWH-z+)2$&$}bRK23DrO%u;)4 z-Anx^L3E)RYp#&{w99pj<(W5a$ppGvxSH2_LLi8Pey<3|aYOw5}$uA+CkB zGQFPiX5toNBk_6SPU0?lHc{R~+)GrM%n#AYl-_zWrOpy+N+B;xA3?c-@*K*Q@Wkj) zQ;A;{K;NL*l)r}7wXC5yOMJpvQh$UPBi0ieiA@%>#dA)MtX)kx(ubxTDYYj@TE{Q! zLe>F}9pw_rVag*YM*>nRLQRagHXu1%8<2CM&GdPmxQqH-&{w7Jv1NlS8+Ncs7o^lBG1O{}MhdX+1+d2*$;V#+1C;@K6Ns`OFB81?nU#$3r> zBjqN_O_Wuh)Ki=%)?&(GVuYFqvbzdo&O{1jCNvR86^UjZv9UnUTT zdPyHtFDdKkC2bW`4ih7^MkvQ9$0*km8;MOs)tjvo!^8+NMqJxlT3p*(TCAt0iKzOp z6fsPU5MzC0*2O5-Q?94nNNl2}iL&Y|o~keFpYJ!n{n@MjteF@lMu_#qMq(3D4WK76 zJV45ZDMu(rD9;-pZOt1XZN;crJ3z*(o<8-|G*WJ)+(fyFvMOis^dF5@1fTu*Ey zHc{V1SqHWHhN>NvJej2tI*MkvRK^~9~m zN&Q=ollmL!(@6cU40(i1oxqViQrFApYSKq}?#(Q71@SqfU^v zBGk+~L0XAXuBT@`=iLWj8Pw>Tu-^4awD;csD`k0Vwe~q#)xZ&NLy=%NL%&PY#kykHd0nYIhsRR12IgD zP#>Wjqa34LPi!PM5!Eo3C3YPqZFLvDniA}?#-6qQFMAkqIpU4rR z9HAVc93$2f8;QG4l(u%AC~Y-Sv+qP{OATjj#4s^Jj1e1$OZ|2PHByH7GZX`AlRhYFA!^8-&J}mXuQ*Ij-HpOgTb~5$lPK#3rH|$<~QsVr-<;AER7P+&WTP**a2MX{2V?NU6Vx zo=w!K3ihgkwGqR_2r)*iCpHqBh-wu5iK9kIE2Bn9E0IxBTZH;~qol1E<$7Wxt&NnM zC^u17qgfjQv5B~Ew6wTyw6v(kNLkMq=536$9;PNjj1lXpuczEdxsh@c zQJu`ziD6=d7$dGdS=w5Avb0rC&DN8ptwzdC#Ntz=-QrWEo-i>&j8Pw>Tu-^4awD;c zsK&B&V%M?KR@br8R+ySmW2LPKWjqa34LPi!Ra8YgY- z8YgWvQL}HHw53jEZNxA!LW~jXiA|?UyG@kUY2xoWjc4GLyHXCH#<8Gg6g3fQBGkl) z^~6SE6H$$4>%^|(nBS6^|Uq;n~3Uk(W}#059MOY zVPb?BBi0ieiA_W`NlJMpNn4&t(pE7wT_;J4Vakz7Qh$tCPb@w|G?6ntL)jRyk=R63 zlSN-l3=<=h=|5T8s;68}xsh@so$`Q&jVm+~u*hExkvMe!7 zj1Xf)dG5vjOCz!^#YeV1-EA*-+uPmtakqWlZ9jM0-`x&yx8?43pu0WJ-5&35PjI(` z-0fg@JH*`%b+^OZ?TPMIe#S@oCqJ(v+pxPG;ciE|+X{C(%H7IOTZq5>$b@Xiy4!K? zHsWqCP(@C)v(tIm`Ox{=@p(@4EcZO-dDHU`&zzL`DLYagNh$Z9>aFyy_HOoW^FH8J zsWqu9Qm;(CC3Q#YZ&Tk)eLq$ELcTkFU-`cG`O*s0x~C0FJ2}mZHdB?OeE4@c((qJ{ zA5s8P5a0Xd;$N%D$J04Q_?7y0(6)!B12i4+Z*P=9(*>Fk*l2YOo`&g+r(a6&^h+t8 ze(8p%UyjAoFFo+|OHXwMp2wMtXK|+Bd6cQD9M7&Cho@goz;~#F@$}13br$|jg0qpg znfP&_bMP(VEYvs~&(_REE-LYTVijs$z<<5w_r8np4F6wq1aC|e^!aOnGbvw4T#yrk z=9B!jz(+jdGoe6mBQ?ioi`B}P6^Z_n{HuUB7f3xP=B@{R8x%Y-_eRQsZRu?(iz__0 zz%yC%s&hwNljXTPE`RLY7ncWncEsh0N%DD~$Kv_}&adKfcTYmTJ4yd&lH4~*9+4!! zZ4zbwoFu0w`5coZuS}9RB*{~fx-lbqZ`hf;>FBO;tol)7CjRrF?6Bq>3n2Fht3!pQYeYwC+n3)>0FduRk%us__ z*bdkobJpOy>|=mEVK;a(tOPg&Gu2@BbpxJ?*=jJ$dH~Ocm%&`@4P1a(D=*pg2i}I6 zi+8s$cMYD0Ist9n4>WjMYcOzt9tteSlVcj+#h(ay1fCu1Tjmk4Mz@2DrTDd1{02VIs7>Z3;H_pO@OE#cF^_;mA*l2zZ&GW#yDwNV2 zSeDWk*ej(!uun=kuwTk?zyT>I00*WF#!MN25fAg(zp0ofm6#>fcxG-j{>AWHF+Uzw zPpU@svU*?b!LxE-;%P&#&eDatSohFXdZ}KaSL>_v4f-~{S#Q^m=wIpQ^~?GX`hC4e z@7G`IZ?!gQCScl|E~d&l=Ajk4`B{DNi{wWo^oyldfTT?PhFL|KK0|&PgB20{WjI_%k}-nmz8!*THiEJ%pQ|)2y*|P#M@BvEO+zY z`h3` z!5%vo$B;_2I1eq(M~mm8#q(f2AKEI8Q6=`{O0^KEa762;-oqQ2dFbylyo)9O4%!AI z`f1#H(C$Bi^6whWP&ZP4mdno~SLzZqqfqRZsJmfTc(TXxl`g-`<(H8cso$_(c{kts z?Q->By6yhU-G1e6zj3$Uy4!>9_CM}cYw532>$uIqUT^tB`Y|J;^N`CQ!S)<=i*t_J zkB{RyN9B9I!@qQXk?QUF8rwD4uEX|we6GUhI&eG#@4j zuGQnyG)70OML7G|j?W^TfqZ~ z%GTDnaN(S}3+G4rtFaZ)MN8&XH?z@;moJ*1U`vWI2xrERxMj$Yo1?Covn9SRM=@% zHOsIWHMb(Vc-j1mMIKW=K#j#`Dn3%*)Uk_~xuTVZRYsRDUN-!=*|P_zG0PWMMh2*) zz79~+<}6%3f6DSD2+AcBmn^G_E(SYe{<(3PO%G5bs;lR$fN5Bj)L4$+9UiFupZ2aU zHje8$-`RiuXvJMgiJg+nqD=|~vG^C+Wl~i!f2~bO>Sswu1q@Kj-640Z=sUu0CJ!p3XlRSpcEG1hZKm5BtRYlxNj}s6iuJ{5I^;y$U|BnD4L>a>we$4cYesF zY^8l`vn1!-d(OFk=bn4cnLBruW&Ca6FKFH*(L9OMXk1w@ks5vlUbv!L=4>jlu$ zGqWg!%Z}}DZmciQsxlC>ajsb^jJmMeuJ1MNiwYvF*}k)DFV4r)6Z4h1^))o!adoP4 z;Q99MMENpoO}W*w-D{syj)6-}d)IFHz}R7m9e{{8l@}z4fxtCJ64J>4gL&ALZbLGr z6cbV^z(8Oc1F2~qNeIvMbEak{q~-tvDVlm9FvBD%;R+gvqEV6{M*qu9jSSMnW5#V4)tMfJInw6aZG+b-sb_E3 zRKf%?S6obX&DYp4LyBmn#+xLui(4{l092@oU*8g?k_2p!GP2Roq1#ptF0;)^m@a^+5_K(i_OhVr{(xgwHYF*`>O0M z+S^Xct}9vQ-bU*dT5Y?|=YhIF9lLmQb9260yNUley6o6ZV5wgHSgKe*mipF@rKh3YLWxML{x%TnIEAU~vHrD3x z_RGa;@4fh!2s=d2qyIw!{oVx?(+VYPfp`zus zyIb}9OH~e9es#YOKiBElt-5O2zUNn4^{QJ}>uuNsI*BHnh+4o>_U&?uWMsYeo(u4T z?O&>TjfHmI7VBUpLhb4aiH8Gl?m1g%+vN57Kl4sZ0|`D?irSq6262Efrz%4 zTXx&K215%{fn5NxEWTR$z!@{02__%?36nHav8h+vks3&;Lo=@!%Y=HMTCAGOtKXYW zT+Wsv3{lAUHiJdo!8dov;|?RVftxn!%&2&>okTH9yWBeWiz?Ot*q=~je4 z#QwQPoD>Xb88h)B6al_FDi;vTt!=RkAXb}wTnklreK)Wy=&*~0e5f8Xwcbj*R%LY1 z-vXlWZD$9%bUb;{_G+#p!E{tMP#8VB2p>fuW`RT`@lTz0lggx>n6?UT#G=FCvW`0t zQN&1?u}XE@_7AQhQ1+rCVn$5JOG6SP1tY(L<>lD7jjG2O^dgX9U$dLleM!aW6&TmU z1C0@b`7!P?>QO*gXm<`=XQ$yuq{>aF!+B_W9Akukyl9Neh**R5Vs4!xf)=Uv77PcvECLyt1TW?tYyr@ z!q|o0R%q}?n(-EcbOe}d_6}y^7Az-J02Obm%}x3r+;pntCN4{@TDuN65|~!g#|g7K zNTDy}|GcMlH!1N$_P)unzr@TtJ4-Eu#jQ&rsj|1_>B6f{&24*jt=+17@LM%|snf1C z)JDtM*C~#2#cu8RK)Q}Jc3B8Vu`kbpmyjolVbh_0|m5bxo}Pv4RR;^16iivm$StaDRs_)hcj?r)-w zZ%Mnp+f-uA=Z1B1pLnm-s;I0IIR8E!FO9zJOBn zgbkftfn}03MZeXr=&x>CnV`!?%n3JAhWxb9#`k@pDiVJ8AML=6{= zoxg}1T;Bwzk0~81b%c2i_sF*xFQ^ILx8f>*K_Zoedn~F_YuMb7ne!#P2sI}C^7c0N zPc(<#fLY^inN#zE0Yo?3o~#DB0rr%L#iZjlB`6jcFj>;=P6ay*PR$N$4agKWgSL>a zV-A=(u5^#KPF!GUj6K*vSxblwH3W-JtYP0xr?$A*!Yx4>SWj!pg^TAmH~oea_9HgB z2}XW%Fhd6(=z2`;ZT~Qu)^Xjb-SpI4y{;3q8ak!74~&Ib+V|}iG)P?bm$F`sJ;cu`Q!2*a8GFF$w~3xH8xWh#*kCn4H65j#cIy{1pS6c2yd4KPqgu{3IKX9qS5Lo!Pn z-sG0!wp$FkL*XCSSF^C zW*s_;tC&Yj7&oTXDsH8?FoTY-Gkpsi=^cAtHSnh`x?b>N zn^CKVn5#fVWZqg>L$X7!%D7eWp*gri?BL4JnRPq^+rf{G=U+>zrS|X?L}g3r3wRo* zCg<>caz}7BXg+Ye$a#|5LYWdum+;JNTFoe&dKtQfd=nh_THhxwJA>!qI6?D-{2M`A zPt0%XPo7hjrOs6FB(EW(-9t}poE!1+eWZ(c3b>%!GDaJ3+ygg6TnWzxA%_7Ev|WyB z0I?3Zkov7Tl&9RbAfu{0DO|_1+zx4S-lm^HJ*p7oH<6R^ z6v}3#F7%Bvrk*~E33;>E&;q{j_@ssrz9RipCp8T5C$FHNZS-pol7<{VcsL*O4N_#IR8ZQ*NGKo9Ta*iV2IkRHoBb~YsgRZ~QzK9C8sRns$7_hoQhT9)CpC=l z)HLEXjPPZg=D>+C@DoOOo=+lP!w6qSEjTd-e!>X9VelG;_-!UL8opeZG_1=&M=)a!^&soTwIa<|I{$MPrH*qK82PZNdiw+r1z!dC3Qs$uW6flujTAjAvYD|GK0 zhPwv7Zr~fHK=1Al8%CpF!I(ho{<$@l4mxo!NZbz+4?b-=^!;3Jtk8YHzhd`cVV^(f z=l63u8C-$-VJ65B>h`-2O+Tg#Ja6Evffo#X-oQlzFB!OE;1vVc4ZLpPO9tLBux?<( zz@~wm4%;gBd;?AYdUuR`q@$RxaSIH9IPWMB7}DhmY!E!6 z27oC|&1jI*V9@Zev*e{70S;?$!n9oM{v}$bdK9lhVH0HjYhY3(oOl3YlnAm6l$0T* zORCuYi5}9Jp5`|&&AQ%vSnoS}MAYuALhXg_&r(^d_zK!8zQT2oFzF(Ixd7J~1l=Q856&2)Ib0Sf^TD*#y3m9mj`&BLZe+xwvVYY|%XM6( z24!stY6Ry>3f(WGb3#0YZ+1!ym695nP9)N(u-i*!twE0K=hjfRlt`R{OxP0UU0Q0e zMk)aq3QbZlF+ypQA{gj|U^>L`GOkXbV`DfyNWqS)e zlFMbX$sCp{yO7JJRU)0w4TmBE=ZS2xaHntwrN3zvU|%$(-k?XOWm1S4OB<1NVE7WF zm`Y>ih^A#oW}tE-7S78+9?0U%7i5c~#aBiPq6orfxG{F9LTFNc&Js9UoXw`B#}Ln8 zDg%Rtq2h`!h68vsIDjsGH<2&&5SF4uvHMyMYEkTd9mW<-W6)_#NcRC|ZCnjzlf~|j zK!h5jx5eJm(0`;wyGAoAna_`oq9I~Np?e(vcTg+Z5}kmdAElA!z+o0#X|RRLDdOUxce>24EhM7%z`fT zJt`;6inb(F#eMWQ%aU0n2ACK?Vu*<$$Zsf{g%^0c&=gI78>AFTDI_vX$Yl_@VdjRB zIKjk;0gUA<(ir>tFOtF<36iM{Bn@T30BJ_pDJm?j1(ls;{!PjZm*^*GSy(_%jX^*W zsESGzdmlwwRt7M66z-*@aDhv^*nI~znu=uOF(FZO1Oy$i+O^Tpm`v3IH1 zTPgOg6npE%-t}VdrDE?!u~#ql8pU3-*z3R-6?^-|-kkw0VYDkFd4N%&htS`#eDSK- zxHqv_x({R#J%FgGphSFVgoc@ur{_x~{w6HUxRn_cjzlJh6)YCyl$9IGg3oA($Y0z( zr-Sl@@Pp~NPa*a07J3f@AwA4zQ)Yr>YNV&%Wlwu|b8mm))Vn`E_s-SR`i4RW_WEYQ zQ{zOwf(X%(n6Qo$pEja1Mv5+CyK&y6?MhhZfrUZkGBDTxl@N1u(L|b;5eqhPXK^es zxE+cUPY3tDhmbEwN9u>F$$bX>V66F}HBcEi@+PHrh-Z+a;Jx9#8Vy=Iwo3uAf+1B= zXT0^yhSZ$7jz*d)h5wpBU(Qpta2pAjdz{U+G8PP|HDC=|L)Nf$0>_0-M4Oo#g(b=%#(+yG z)C=`ATo$e+g(v~(LLIJ?7=#IM{BZrCG^I#GiZluhDbf%&UULW*SQ(fFr@1?V>l8YI z>%di6`EfNoVqwKWR&?%J;KtH$+CUN}P%*3{S;v*W!D!+O<-kpcJeD2|)AC! zRG6Y0pAs{sy)b7c53Q9EJVZi|fT{Ut1pm`J5j0MdKNpVpe^C)FGbR_aiNOuP{&JSb zEqYAt-eVq9BXsMpafonc31rjYF zR8$~^EPcLdEQ4$=%I1(AjIx8Qtd4w8JJt&#=oq4b0>e>(VPsE4*%M$Nb)o`R85qnhuGjWdIY~k00ldZ zN~{sC3&W__MeivD5t@+zj87THM_`m?6EuR1w0ke!?ma;vP6@c^H`zPf9!DrTYb>Lj z?i*r*DcvLil^-j{8p*L?n%@iz8vvqll#vuyFyo2yx)=e9okv5~NW_3>V^%W|fMFIZ zj2bExA)%W`L~=p15rFN2j2Luwqp(kdNRgv)xB+Pz5zO$+l_=d(KUTbPR0q{+YM-bQ1cmm)% z8jr}%*LVWpeT_%Bx3BR8z#DPjK^Um<1i(|_F+Y(?g_C)gk#J-bY1SDx>(X}*n{`7# zeRo+c<2)K?sxaredr$Z3^b@@Z1|oD_iU6hFFr~=I zPKL_?ndDjgua>h4QOjACKw^x!u~FoPkbqA|ID!dAT(O?`z~|g*XRX}|pT^_xGtS^4ppsxjsTc5l%oA%%>p09Ihc2Hn zXA1t{*385-YRI1s&ykr|L-<6tz#^rfObM*`w&pxuB&prxiL=s5b<0y~81KO09Fkqd zi9m&ySyD4oGuS4sTI!|shFyvs0x8K`044L7v*h4GoSgahN^@7rUTM4S8V(Onr}3oc z^K$5563>X^`I6HrE&L9)RoU?L#1wy&`n07!C7E+>ZTeiJ?Qc8#(;uJSs&3V`YqQUO z^0{Yct24h>o1WU*-roMiv$ZMP-mZVLdVc0v@ZkMs+<*_ox{7zMA+i`kzsnGwzGQnR z@JPLl=cG6ogU6%KGK>?f}xH0qb*h?@$Kxv`m?^^0ryvvn<3Y?g0;(Wp?o?AMQDi8zZ7EVIoDQ=x? zE2p1`4RyY6ZD%a?uKXXqqis+p->)kuJe*>9e6;YpUplU^b(C%R2|5U^m&jY8vFE|x z-`HKypP;84(2>HZ@}Dw&SP1wn)3KP?k4}mOwvu6cpXut#D~3la=o8voPattLI{N;7 zQyZH}P)&2M?LBw$Uym%{!#< zE{ghTNO%KNlT2RjCdrEFA0m{`H=Y^%fwESwu;5?d@296N_0xaVG+tRbUc;6_ehriR zwOIhcTI zvr&()ejNV5Q677;gA?dZZL)^LRkk;|<={YHYsWiR!x=lbGbzS0FgTMqqc>@+>}2fp zJZy5j=EGKMqJx)iDwpOUY-KwA4?(9Xn3whwJ-I?*F(1_=YgwDpuXY1Jy)&qSufr;|=OHVYu?@y2w|qXljU6(6J|d;oLFMk22Rfew9i@2}~5!ZU@F6#C~pb_5{<^>=uq8{Ywd`gUb2j%QR5Tj4!Pp7AK5R_?3u zSuk7WX5FHi2Yw!uIdH8ZeGS`qET`!_r@;+Ij)eTW#uB)%U}QYO!LhkV>fjS-ZUgcx zg@ZS{qft)cnKVyrJdV!xTBvOS-zmZGp;79hd`m^J(Mh=-pr6q*>IJmHr`k8wZRyEP zlwJWHFAhrim+;*xRyZ4r(mJ1$I~Y}5_Q%U+A|{)OBeGGDIW}Fwx?hx0aU(XE&uNTd zD*VH@tKi9yB^tr4S{GxXgrd>>`hA#yJe&AI{HL&8hLLlpm9h zW_bDnpStwrvY}JzEEVV)bDVGW7@c`9xkP=M#arhVG$nolCK~PI>Q?w4Pru(+?x=Jl z*`7oFHJlAOC#NZVXrzOk=4pJF0l#~Knot9-hEp!j;`=6^!*v$e8GPpmOHF~kEkB^FJaYlMx)t}`bQo3&F9ya0Pdw2 Prw`-M(QiKg|0M9=+-bOc diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll deleted file mode 100755 index 9a42883edac922e401bd6ba877a45441258858a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57344 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

    - Read a value of type T from the passed span, which is assumed to be in little-endian format. - The behavior of this method is independent of the endianness of the host, unlike MemoryMarshal.Read. - - - - - - - - Read a value of type T from the passed span, which is assumed to be in big-endian format. - The behavior of this method is independent of the endianness of the host, unlike MemoryMarshal.Read. - - - - - Convert the passed byte array to a value of type T, optionally reversing it before performing the conversion. @@ -151,36 +130,7 @@ - - - - - - Convert the passed T to a little-endian byte array. - The behavior of this method is independent of the endianness of the host, unlike MemoryMarshal.Read. - - - - - - - - Convert the passed T to a big-endian byte array. - The behavior of this method is independent of the endianness of the host, unlike MemoryMarshal.Read. - - - - - - - - Convert the passed T to a byte array, and optionally reverse the array before returning it. - If the output is not reversed, it will have the native endianness of the host system. - (The endianness of the host system can be checked via System.BitConverter.IsLittleEndian.) - - - - + @@ -190,17 +140,7 @@ - - - Read a value from a "big-endian" hex string. - All hex strings we expect to encounter are big-endian (store most significant bytes - at low indexes) so this should always be used. - - - - - - + Create an Address from a LITTLE-ENDIAN byte array. @@ -211,7 +151,7 @@ - + List PreProcessUnsubscribeApplied(UnsubscribeApplied unsubApplied) { - var table = clientDB.GetTable(unsubApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {unsubApplied.Rows.TableName}"); + var table = Db.GetTable(unsubApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {unsubApplied.Rows.TableName}"); var dbOps = new List(); // First apply all of the state @@ -652,7 +659,7 @@ ProcessedMessage CalculateStateDiff(PreProcessedMessage preProcessedMessage) // the client cache. if (preProcessedMessage.subscriptionInserts is { } subscriptionInserts) { - foreach (var table in clientDB.GetTables()) + foreach (var table in Db.GetTables()) { if (!subscriptionInserts.TryGetValue(table.ClientTableType, out var hashSet)) { @@ -691,7 +698,7 @@ public void Disconnect() /// /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - internal void Connect(string? token, string uri, string addressOrName, Compression compression, bool light) + void IDbConnection.Connect(string? token, string uri, string addressOrName, Compression compression, bool light) { isClosing = false; @@ -751,11 +758,7 @@ private void OnMessageProcessCompleteUpdate(IEventContext eventContext, List _messageQueue.Add(new UnprocessedMessage { bytes = bytes, timestamp = timestamp }); // TODO: this should become [Obsolete] but for now is used by autogenerated code. - public void InternalCallReducer(T args, CallReducerFlags flags) - where T : IReducerArgs, new() + void IDbConnection.InternalCallReducer(T args, CallReducerFlags flags) { if (!webSocket.IsConnected) { @@ -1055,7 +1053,7 @@ void IDbConnection.Subscribe(ISubscriptionHandle handle, string querySql) /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("SELECT * FROM table WHERE sender = \"bob\""); [Obsolete("This is replaced by ctx.Db.TableName.RemoteQuery(\"WHERE ...\")", false)] - public Task OneOffQuery(string query) where T : IDatabaseRow, new() => + public Task OneOffQuery(string query) where T : IStructuralReadWrite, new() => ((IDbConnection)this).RemoteQuery(query); async Task IDbConnection.RemoteQuery(string query) @@ -1101,7 +1099,7 @@ T[] LogAndThrow(string error) } var resultTable = result.Tables[0]; - var cacheTable = clientDB.GetTable(resultTable.TableName); + var cacheTable = Db.GetTable(resultTable.TableName); if (cacheTable?.ClientTableType != typeof(T)) { @@ -1140,6 +1138,12 @@ void IDbConnection.Unsubscribe(QueryId queryId) })); } + + void IDbConnection.AddOnConnect(Action cb) => onConnect += cb; + + void IDbConnection.AddOnConnectError(WebSocket.ConnectErrorEventHandler cb) => webSocket.OnConnectError += cb; + + void IDbConnection.AddOnDisconnect(WebSocket.CloseEventHandler cb) => webSocket.OnClose += cb; } internal struct UintAllocator diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index a0acaf37a4d..35d76bb496d 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -7,13 +7,11 @@ namespace SpacetimeDB { - public interface IDatabaseRow : IStructuralReadWrite { } - - public abstract class RemoteBase + public abstract class RemoteBase { - protected readonly DbConnection conn; + protected readonly IDbConnection conn; - protected RemoteBase(DbConnection conn) + protected RemoteBase(IDbConnection conn) { this.conn = conn; } @@ -21,51 +19,105 @@ protected RemoteBase(DbConnection conn) public interface IRemoteTableHandle { - // These methods need to be overridden by autogen. - object? GetPrimaryKey(IDatabaseRow row); - void InternalInvokeValueInserted(IDatabaseRow row); - void InternalInvokeValueDeleted(IDatabaseRow row); + internal object? GetPrimaryKey(IStructuralReadWrite row); + internal string RemoteTableName { get; } - // These are provided by RemoteTableHandle. internal Type ClientTableType { get; } - internal IEnumerable> IterEntries(); - internal bool InsertEntry(byte[] rowBytes, IDatabaseRow value); + internal IEnumerable> IterEntries(); + internal bool InsertEntry(byte[] rowBytes, IStructuralReadWrite value); internal bool DeleteEntry(byte[] rowBytes); - internal IDatabaseRow DecodeValue(byte[] bytes); + internal IStructuralReadWrite DecodeValue(byte[] bytes); - internal void InvokeInsert(IEventContext context, IDatabaseRow row); - internal void InvokeDelete(IEventContext context, IDatabaseRow row); - internal void InvokeBeforeDelete(IEventContext context, IDatabaseRow row); - internal void InvokeUpdate(IEventContext context, IDatabaseRow oldRow, IDatabaseRow newRow); - - internal void Initialize(string name, IDbConnection conn); + internal void InvokeInsert(IEventContext context, IStructuralReadWrite row); + internal void InvokeDelete(IEventContext context, IStructuralReadWrite row); + internal void InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row); + internal void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructuralReadWrite newRow); } - public abstract class RemoteTableHandle : IRemoteTableHandle + public abstract class RemoteTableHandle : RemoteBase, IRemoteTableHandle where EventContext : class, IEventContext - where Row : IDatabaseRow, new() + where Row : class, IStructuralReadWrite, new() { - string? name; - IDbConnection? conn; + public abstract class IndexBase + where Column : IEquatable + { + protected abstract Column GetKey(Row row); + } - void IRemoteTableHandle.Initialize(string name, IDbConnection conn) + public abstract class UniqueIndexBase : IndexBase + where Column : IEquatable { - this.name = name; - this.conn = conn; + private readonly Dictionary cache = new(); + + public UniqueIndexBase(RemoteTableHandle table) + { + table.OnInternalInsert += row => cache.Add(GetKey(row), row); + table.OnInternalDelete += row => cache.Remove(GetKey(row)); + } + + public Row? Find(Column value) => cache.TryGetValue(value, out var row) ? row : null; } - // These methods need to be overridden by autogen. - public virtual object? GetPrimaryKey(IDatabaseRow row) => null; - public virtual void InternalInvokeValueInserted(IDatabaseRow row) { } - public virtual void InternalInvokeValueDeleted(IDatabaseRow row) { } + public abstract class BTreeIndexBase : IndexBase + where Column : IEquatable, IComparable + { + // TODO: change to SortedDictionary when adding support for range queries. + private readonly Dictionary> cache = new(); + + public BTreeIndexBase(RemoteTableHandle table) + { + table.OnInternalInsert += row => + { + var key = GetKey(row); + if (!cache.TryGetValue(key, out var rows)) + { + rows = new(); + cache.Add(key, rows); + } + rows.Add(row); + }; + + table.OnInternalDelete += row => + { + var key = GetKey(row); + var keyCache = cache[key]; + keyCache.Remove(row); + if (keyCache.Count == 0) + { + cache.Remove(key); + } + }; + } + + public IEnumerable Filter(Column value) => + cache.TryGetValue(value, out var rows) ? rows : Enumerable.Empty(); + } + + protected abstract string RemoteTableName { get; } + string IRemoteTableHandle.RemoteTableName => RemoteTableName; + + public RemoteTableHandle(IDbConnection conn) : base(conn) { } + + // This method needs to be overridden by autogen. + protected virtual object? GetPrimaryKey(Row row) => null; + + // These events are used by indices to add/remove rows to their dictionaries. + // TODO: figure out if they can be merged into regular OnInsert / OnDelete. + // I didn't do that because that delays the index updates until after the row is processed. + // In theory, that shouldn't be the issue, but I didn't want to break it right before leaving :) + private event Action? OnInternalInsert; + private event Action? OnInternalDelete; + + // These are implementations of the type-erased interface. + object? IRemoteTableHandle.GetPrimaryKey(IStructuralReadWrite row) => GetPrimaryKey((Row)row); // These are provided by RemoteTableHandle. Type IRemoteTableHandle.ClientTableType => typeof(Row); private readonly Dictionary Entries = new(Internal.ByteArrayComparer.Instance); - IEnumerable> IRemoteTableHandle.IterEntries() => - Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)); + IEnumerable> IRemoteTableHandle.IterEntries() => + Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)); /// /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. @@ -73,7 +125,19 @@ IEnumerable> IRemoteTableHandle.IterEntries() /// The BSATN encoded bytes of the row to retrieve. /// The parsed row encoded by the rowBytes. /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. - bool IRemoteTableHandle.InsertEntry(byte[] rowBytes, IDatabaseRow value) => Entries.TryAdd(rowBytes, (Row)value); + bool IRemoteTableHandle.InsertEntry(byte[] rowBytes, IStructuralReadWrite value) + { + var row = (Row)value; + if (Entries.TryAdd(rowBytes, row)) + { + OnInternalInsert?.Invoke(row); + return true; + } + else + { + return false; + } + } /// /// Deletes a value from the table. @@ -82,8 +146,9 @@ IEnumerable> IRemoteTableHandle.IterEntries() /// True if and only if the value was previously resident and has been deleted. bool IRemoteTableHandle.DeleteEntry(byte[] rowBytes) { - if (Entries.Remove(rowBytes)) + if (Entries.Remove(rowBytes, out var row)) { + OnInternalDelete?.Invoke(row); return true; } @@ -92,7 +157,7 @@ bool IRemoteTableHandle.DeleteEntry(byte[] rowBytes) } // The function to use for decoding a type value. - IDatabaseRow IRemoteTableHandle.DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); + IStructuralReadWrite IRemoteTableHandle.DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); public delegate void RowEventHandler(EventContext context, Row row); public event RowEventHandler? OnInsert; @@ -106,21 +171,19 @@ bool IRemoteTableHandle.DeleteEntry(byte[] rowBytes) public IEnumerable Iter() => Entries.Values; - protected IEnumerable Query(Func filter) => Iter().Where(filter); - public Task RemoteQuery(string query) => - conn!.RemoteQuery($"SELECT {name!}.* FROM {name!} {query}"); + conn.RemoteQuery($"SELECT {RemoteTableName}.* FROM {RemoteTableName} {query}"); - void IRemoteTableHandle.InvokeInsert(IEventContext context, IDatabaseRow row) => + void IRemoteTableHandle.InvokeInsert(IEventContext context, IStructuralReadWrite row) => OnInsert?.Invoke((EventContext)context, (Row)row); - void IRemoteTableHandle.InvokeDelete(IEventContext context, IDatabaseRow row) => + void IRemoteTableHandle.InvokeDelete(IEventContext context, IStructuralReadWrite row) => OnDelete?.Invoke((EventContext)context, (Row)row); - void IRemoteTableHandle.InvokeBeforeDelete(IEventContext context, IDatabaseRow row) => + void IRemoteTableHandle.InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row) => OnBeforeDelete?.Invoke((EventContext)context, (Row)row); - void IRemoteTableHandle.InvokeUpdate(IEventContext context, IDatabaseRow oldRow, IDatabaseRow newRow) => + void IRemoteTableHandle.InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructuralReadWrite newRow) => OnUpdate?.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); } } diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 1287a5fdea4..bbedc297919 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -7,12 +7,12 @@ }, OnInsertUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.SubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, user: { identity: Identity_1, @@ -22,8 +22,6 @@ LogException: Unknown reducer unknown-reducer (Parameter 'Reducer'), OnInsertUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -35,11 +33,13 @@ CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - $type: Reducer.StdbIdentityConnected + $type: Reducer.IdentityConnected } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, user: { identity: Identity_2, @@ -48,8 +48,6 @@ }, OnUpdateUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -66,7 +64,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, oldUser: { identity: Identity_1, @@ -79,8 +79,6 @@ } }, OnSetName: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -97,12 +95,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -119,7 +117,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_2, @@ -128,8 +128,6 @@ } }, OnSendMessage: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -146,12 +144,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnUpdateUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -168,7 +166,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, oldUser: { identity: Identity_2, @@ -181,8 +181,6 @@ } }, OnSetName: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -199,12 +197,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -221,7 +219,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_1, @@ -230,8 +230,6 @@ } }, OnSendMessage: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -248,12 +246,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -270,7 +268,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_2, @@ -279,8 +279,6 @@ } }, OnSendMessage: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -297,12 +295,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnUpdateUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -314,11 +312,13 @@ CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - $type: Reducer.StdbIdentityDisconnected + $type: Reducer.IdentityDisconnected } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, oldUser: { identity: Identity_2, @@ -333,8 +333,6 @@ }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -351,7 +349,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_1, @@ -360,8 +360,6 @@ } }, OnSendMessage: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -378,7 +376,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} } }, FinalSnapshot: { diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index ac76990117e..094d87e3f15 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -7,12 +7,12 @@ }, OnInsertUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.SubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, user: { identity: Identity_1, @@ -22,8 +22,6 @@ LogException: Unknown reducer unknown-reducer (Parameter 'Reducer'), OnInsertUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -35,11 +33,13 @@ CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - $type: Reducer.StdbIdentityConnected + $type: Reducer.IdentityConnected } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, user: { identity: Identity_2, @@ -48,8 +48,6 @@ }, OnUpdateUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -66,7 +64,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, oldUser: { identity: Identity_1, @@ -79,8 +79,6 @@ } }, OnSetName: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -97,12 +95,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -119,7 +117,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_2, @@ -128,8 +128,6 @@ } }, OnSendMessage: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -146,12 +144,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnUpdateUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -168,7 +166,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, oldUser: { identity: Identity_2, @@ -181,8 +181,6 @@ } }, OnSetName: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -199,12 +197,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -221,7 +219,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_1, @@ -230,8 +230,6 @@ } }, OnSendMessage: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -248,12 +246,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -270,7 +268,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_2, @@ -279,8 +279,6 @@ } }, OnSendMessage: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -297,12 +295,12 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnUpdateUser: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -314,11 +312,13 @@ CallerAddress: Guid_1, EnergyConsumed: {}, Reducer: { - $type: Reducer.StdbIdentityDisconnected + $type: Reducer.IdentityDisconnected } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, oldUser: { identity: Identity_2, @@ -333,8 +333,6 @@ }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -351,7 +349,9 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_1, @@ -360,8 +360,6 @@ } }, OnSendMessage: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.Reducer, ReducerEvent: { @@ -378,16 +376,18 @@ } } }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, OnDeleteMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.UnsubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_2, @@ -397,12 +397,12 @@ }, OnDeleteMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.UnsubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_1, @@ -412,12 +412,12 @@ }, OnDeleteMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.UnsubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_2, @@ -427,12 +427,12 @@ }, OnDeleteMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.UnsubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_1, @@ -443,12 +443,12 @@ LogWarning: Subscription Error: $bad query dude, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.SubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_2, @@ -458,12 +458,12 @@ }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.SubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_1, @@ -473,12 +473,12 @@ }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.SubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_2, @@ -488,12 +488,12 @@ }, OnInsertMessage: { eventContext: { - Reducers: {Scrubbed}, - SetReducerFlags: {}, Event: { $type: Event.SubscribeApplied }, - Db: {Scrubbed} + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} }, message: { sender: Identity_1, diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index df57fde3042..532fe22c8ed 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -307,7 +307,7 @@ public static IEnumerable SampleDump() ), SampleTransactionUpdate( 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "__identity_connected__", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], + 0, "identity_connected", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], null ), SampleTransactionUpdate( @@ -343,7 +343,7 @@ public static IEnumerable SampleDump() ), SampleTransactionUpdate( 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "__identity_disconnected__", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], + 0, "identity_disconnected", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], null ), SampleTransactionUpdate( @@ -373,7 +373,7 @@ public static IEnumerable SampleDump() ), SampleTransactionUpdate( 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "__identity_connected__", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], + 0, "identity_connected", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], null ), SampleTransactionUpdate( @@ -409,7 +409,7 @@ public static IEnumerable SampleDump() ), SampleTransactionUpdate( 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "__identity_disconnected__", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], + 0, "identity_disconnected", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], null ), SampleTransactionUpdate( @@ -536,7 +536,7 @@ await Verify( new EnergyQuantaConverter() ])) .ScrubMember(x => x.Status) - .ScrubMember>(x => x.Db) + .ScrubMember(x => x.Db) .ScrubMember(x => x.Reducers); } } diff --git a/sdks/csharp/tools~/gen-client-api.bat b/sdks/csharp/tools~/gen-client-api.bat index 23196f94b72..ead3c8ca8ab 100644 --- a/sdks/csharp/tools~/gen-client-api.bat +++ b/sdks/csharp/tools~/gen-client-api.bat @@ -1,20 +1,15 @@ @echo off setlocal -if "%CL_HOME%"=="" ( - echo "Variable CL_HOME not set" - exit /b 1 -) +set "STDB_PATH=%1" +set "SDK_PATH=%~dp0.." -cd %CL_HOME%\SpacetimeDB\crates\client-api-messages -cargo run --example get_ws_schema > %CL_HOME%/schema.json +cargo run --manifest-path %STDB_PATH%/crates/client-api-messages/Cargo.toml --example get_ws_schema | ^ +cargo run --manifest-path %STDB_PATH%/crates/cli/Cargo.toml -- generate -l csharp --namespace SpacetimeDB.ClientApi ^ + --module-def ^ + -o %SDK_PATH%/src/SpacetimeDB/ClientApi/.output -cd %CL_HOME%\SpacetimeDB\crates\cli -cargo run -- generate -l csharp --namespace SpacetimeDB.ClientApi ^ - --module-def %CL_HOME%\schema.json ^ - -o %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi +move "%SDK_PATH%\src\SpacetimeDB\ClientApi\.output\Types\*" "%SDK_PATH%\src\SpacetimeDB\ClientApi" +rmdir /s /q "%SDK_PATH%\src\SpacetimeDB\ClientApi\.output" -cd %CL_HOME%\spacetimedb-csharp-sdk\src\SpacetimeDB\ClientApi -del /q _Globals - -del %CL_HOME%\schema.json +endlocal diff --git a/sdks/csharp/tools~/gen-client-api.sh b/sdks/csharp/tools~/gen-client-api.sh index a34fd0d6630..0d840e834a9 100755 --- a/sdks/csharp/tools~/gen-client-api.sh +++ b/sdks/csharp/tools~/gen-client-api.sh @@ -6,6 +6,7 @@ SDK_PATH="$(dirname "$0")/.." cargo run --manifest-path $STDB_PATH/crates/client-api-messages/Cargo.toml --example get_ws_schema | cargo run --manifest-path $STDB_PATH/crates/cli/Cargo.toml -- generate -l csharp --namespace SpacetimeDB.ClientApi \ --module-def \ - -o $SDK_PATH/src/SpacetimeDB/ClientApi + -o $SDK_PATH/src/SpacetimeDB/ClientApi/.output -rm -rf $SDK_PATH/src/SpacetimeDB/ClientApi/_Globals +mv $SDK_PATH/src/SpacetimeDB/ClientApi/.output/Types/* $SDK_PATH/src/SpacetimeDB/ClientApi/ +rm -rf $SDK_PATH/src/SpacetimeDB/ClientApi/.output diff --git a/sdks/csharp/tools~/gen-quickstart.sh b/sdks/csharp/tools~/gen-quickstart.sh new file mode 100755 index 00000000000..af0b12b7776 --- /dev/null +++ b/sdks/csharp/tools~/gen-quickstart.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -ueo pipefail + +STDB_PATH="$1" +SDK_PATH="$(dirname "$0")/.." +SDK_PATH="$(realpath "$SDK_PATH")" + +cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- generate -y -l csharp -o "$SDK_PATH/examples~/quickstart/client/module_bindings" --project-path "$STDB_PATH/modules/quickstart-chat" diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index a8d9e359875..9954ea7d72c 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit a8d9e359875ad22b409fda8be204e53d2d7b96e7 +Subproject commit 9954ea7d72c6cc70820710085d4d93612f849652 From fed2a9db3e502090e7d9bf3dfbb466dc0cd36687 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 6 Feb 2025 17:54:12 +0000 Subject: [PATCH 170/223] Fix handling of multi-tables (#229) ## Description of Changes Unfortunately, none of our tests currently cover this, but while working on the V9 upgrade, I noticed that this code still relies on `type(Row)` as a unique table identifier. That no longer holds with multi-tables as several tables can share the same `Row` type. In that case, subscription updates would be grouped incorrectly and always applied to the same first table that uses `Row` for its data storage. This PR fixes that by using the table handle itself as a key (compared by reference). If transaction updates are already grouped uniquely by table, it should be possible to simplify this code much further, but I'm not sure if such guarantee exists, so leaving that untouched. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] I did `dotnet test`, but as mentioned in the description, this requires adding tests for multi-table subscriptions, which I'm afraid I won't have time to do, so have to leave to follow-up devs. --------- Co-authored-by: james gilles --- sdks/csharp/src/RemoteTablesBase.cs | 2 - sdks/csharp/src/SpacetimeDBClient.cs | 76 ++++++++++++---------------- 2 files changed, 31 insertions(+), 47 deletions(-) diff --git a/sdks/csharp/src/RemoteTablesBase.cs b/sdks/csharp/src/RemoteTablesBase.cs index 43b68dcd4ed..1403fe98ab5 100644 --- a/sdks/csharp/src/RemoteTablesBase.cs +++ b/sdks/csharp/src/RemoteTablesBase.cs @@ -22,7 +22,5 @@ protected void AddTable(IRemoteTableHandle table) Log.Error($"We don't know that this table is: {name}"); return null; } - - internal IEnumerable GetTables() => tables.Values; } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 2e7bdd3771c..852b536ee95 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -4,13 +4,13 @@ using System.IO; using System.IO.Compression; using System.Linq; -using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; using SpacetimeDB.BSATN; using SpacetimeDB.Internal; using SpacetimeDB.ClientApi; using Thread = System.Threading.Thread; +using System.Diagnostics; namespace SpacetimeDB { @@ -232,7 +232,7 @@ struct ProcessedMessage struct PreProcessedMessage { public ProcessedMessage processed; - public Dictionary>? subscriptionInserts; + public Dictionary>? subscriptionInserts; } private readonly BlockingCollection _messageQueue = @@ -366,20 +366,20 @@ void PreProcessMessages() } } - (List, Dictionary>) PreProcessLegacySubscription(InitialSubscription initSub) + (List, Dictionary>) PreProcessLegacySubscription(InitialSubscription initSub) { var dbOps = new List(); // This is all of the inserts int cap = initSub.DatabaseUpdate.Tables.Sum(a => (int)a.NumRows); // FIXME: shouldn't this be `new(initSub.DatabaseUpdate.Tables.Length)` ? - Dictionary> subscriptionInserts = new(capacity: cap); + Dictionary> subscriptionInserts = new(capacity: cap); - HashSet GetInsertHashSet(System.Type tableType, int tableSize) + HashSet GetInsertHashSet(IRemoteTableHandle table, int tableSize) { - if (!subscriptionInserts.TryGetValue(tableType, out var hashSet)) + if (!subscriptionInserts.TryGetValue(table, out var hashSet)) { hashSet = new HashSet(capacity: tableSize, comparer: ByteArrayComparer.Instance); - subscriptionInserts[tableType] = hashSet; + subscriptionInserts[table] = hashSet; } return hashSet; } @@ -387,7 +387,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) // First apply all of the state foreach (var (table, update) in GetTables(initSub.DatabaseUpdate)) { - var hashSet = GetInsertHashSet(table.ClientTableType, (int)update.NumRows); + var hashSet = GetInsertHashSet(table, (int)update.NumRows); PreProcessInsertOnlyTable(table, update, dbOps, hashSet); } @@ -398,22 +398,27 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) /// TODO: the dictionary is here for backwards compatibility and can be removed /// once we get rid of legacy subscriptions. /// - (List, Dictionary>) PreProcessSubscribeApplied(SubscribeApplied subscribeApplied) + (List, Dictionary>) PreProcessSubscribeApplied(SubscribeApplied subscribeApplied) { var table = Db.GetTable(subscribeApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {subscribeApplied.Rows.TableName}"); var dbOps = new List(); - HashSet inserts = new(); + HashSet inserts = new(comparer: ByteArrayComparer.Instance); PreProcessInsertOnlyTable(table, subscribeApplied.Rows.TableRows, dbOps, inserts); - var result = new Dictionary>(); - result[table.ClientTableType] = inserts; + var result = new Dictionary> + { + [table] = inserts + }; return (dbOps, result); } void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, List dbOps, HashSet inserts) { + // In debug mode, make sure we use a byte array comparer in HashSet and not a reference-equal `byte[]` by accident. + Debug.Assert(inserts.Comparer is ByteArrayComparer); + foreach (var cqu in update.Updates) { var qu = DecompressDecodeQueryUpdate(cqu); @@ -437,7 +442,6 @@ void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, Lis dbOps.Add(op); } } - } @@ -479,8 +483,10 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) { var dbOps = new List(); - // All row updates that have a primary key, this contains inserts, deletes and updates - var primaryKeyChanges = new Dictionary<(System.Type tableType, object primaryKeyValue), DbOp>(); + // All row updates that have a primary key, this contains inserts, deletes and updates. + // TODO: is there any guarantee that transaction update contains each table only once, aka updates are already grouped by table? + // If so, we could simplify this and other methods by moving the dictionary inside the main loop and using only the primary key as key. + var primaryKeyChanges = new Dictionary<(IRemoteTableHandle table, object primaryKeyValue), DbOp>(); // First apply all of the state foreach (var (table, update) in GetTables(updates)) @@ -494,12 +500,12 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) if (pk != null) { // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, pk); + // Consists of the table handle (for faster comparison that string names) + actual primary key of the row. + var key = (table, pk); if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) + if (oldOp.insert is not null) { Log.Warn($"Update with the same primary key was applied multiple times! tableName={update.TableName}"); // TODO(jdetter): Is this a correctable error? This would be a major error on the @@ -507,13 +513,7 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) continue; } - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - op = new DbOp - { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; + op.delete = oldOp.delete; } primaryKeyChanges[key] = op; } @@ -529,12 +529,12 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) if (pk != null) { // Compound key that we use for lookup. - // Consists of type of the table (for faster comparison that string names) + actual primary key of the row. - var key = (table.ClientTableType, pk); + // Consists of the table handle (for faster comparison that string names) + actual primary key of the row. + var key = (table, pk); if (primaryKeyChanges.TryGetValue(key, out var oldOp)) { - if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) + if (oldOp.delete is not null) { Log.Warn($"Update with the same primary key was applied multiple times! tableName={update.TableName}"); // TODO(jdetter): Is this a correctable error? This would be a major error on the @@ -542,13 +542,7 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) continue; } - var (insertOp, deleteOp) = op.insert is not null ? (op, oldOp) : (oldOp, op); - op = new DbOp - { - table = insertOp.table, - delete = deleteOp.delete, - insert = insertOp.insert, - }; + op.insert = oldOp.insert; } primaryKeyChanges[key] = op; } @@ -587,7 +581,7 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) ReducerEvent? reducerEvent = default; // This is all of the inserts, used for updating the stale but un-cleared client cache. - Dictionary>? subscriptionInserts = null; + Dictionary>? subscriptionInserts = null; switch (message) { @@ -659,16 +653,8 @@ ProcessedMessage CalculateStateDiff(PreProcessedMessage preProcessedMessage) // the client cache. if (preProcessedMessage.subscriptionInserts is { } subscriptionInserts) { - foreach (var table in Db.GetTables()) + foreach (var (table, hashSet) in subscriptionInserts) { - if (!subscriptionInserts.TryGetValue(table.ClientTableType, out var hashSet)) - { - // We don't know if the user is waiting for subscriptions on other tables. - // Leave the stale data for untouched tables in the cache; this is - // the best we can do. - continue; - } - foreach (var (rowBytes, oldValue) in table.IterEntries().Where(kv => !hashSet.Contains(kv.Key))) { processed.dbOps.Add(new DbOp From b4aa612239b5227ea4293f831388dbfa4628a7ac Mon Sep 17 00:00:00 2001 From: james gilles Date: Fri, 7 Feb 2025 14:17:45 -0500 Subject: [PATCH 171/223] Make Timestamp and TimeDuration special types (#233) ## Description of Changes C# part of https://github.com/clockworklabs/SpacetimeDB/pull/1836 Needs to be rebased onto https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/220 once that is merged. ## API - [x] This is an API breaking change to the SDK ScheduleAt is now constructed in slightly different ways. ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: phoebe/timestamp-special-type ## Testing Will need an update to blackholio as well. --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 3 ++ .../examples~/quickstart/client/client.csproj | 3 +- .../client/module_bindings/Types/Message.g.cs | 4 +-- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 66560 -> 64512 bytes sdks/csharp/src/Event.cs | 2 +- .../ClientApi/InitialSubscription.g.cs | 8 ++--- .../ClientApi/OneOffQueryResponse.g.cs | 8 ++--- .../SpacetimeDB/ClientApi/QueryId.g.cs.meta | 6 ++-- .../ClientApi/SubscribeApplied.g.cs.meta | 6 ++-- .../ClientApi/SubscribeRows.g.cs.meta | 6 ++-- .../ClientApi/SubscribeSingle.g.cs.meta | 6 ++-- .../ClientApi/SubscriptionError.g.cs.meta | 6 ++-- .../src/SpacetimeDB/ClientApi/Timestamp.g.cs | 28 ------------------ .../SpacetimeDB/ClientApi/Timestamp.g.cs.meta | 11 ------- .../ClientApi/TransactionUpdate.g.cs | 13 ++++---- .../ClientApi/Unsubscribe.g.cs.meta | 6 ++-- .../ClientApi/UnsubscribeApplied.g.cs.meta | 6 ++-- sdks/csharp/src/SpacetimeDBClient.cs | 4 +-- ...p_dumpName=LegacySubscribeAll.verified.txt | 28 +++++++++--------- ...ump_dumpName=SubscribeApplied.verified.txt | 28 +++++++++--------- sdks/csharp/tests~/SnapshotTests.cs | 18 +++++------ sdks/csharp/tools~/gen-client-api.sh | 3 ++ sdks/csharp/unity-tests~ | 2 +- 24 files changed, 86 insertions(+), 119 deletions(-) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs.meta diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 20c5a709b1c..b966f650797 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -21,6 +21,7 @@ $(DefaultItemExcludes);*~/** packages + true @@ -29,6 +30,8 @@ + + diff --git a/sdks/csharp/examples~/quickstart/client/client.csproj b/sdks/csharp/examples~/quickstart/client/client.csproj index 48917cce783..c40f16d6cc4 100644 --- a/sdks/csharp/examples~/quickstart/client/client.csproj +++ b/sdks/csharp/examples~/quickstart/client/client.csproj @@ -2,12 +2,13 @@ Exe - net7.0 + net8.0 false disable enable false + true diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs index 164328ac107..09ddde48c83 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs @@ -16,13 +16,13 @@ public sealed partial class Message [DataMember(Name = "sender")] public SpacetimeDB.Identity Sender; [DataMember(Name = "sent")] - public ulong Sent; + public SpacetimeDB.Timestamp Sent; [DataMember(Name = "text")] public string Text; public Message( SpacetimeDB.Identity Sender, - ulong Sent, + SpacetimeDB.Timestamp Sent, string Text ) { diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 38d8b13aaa984e87a34cc2cd2ea93b6d0a7a0299..2f0ffff19fa98a27c64b5b85fb8c835148bf6c2d 100755 GIT binary patch delta 238 zcmZoT!Q60yc|r$E-miOmH}*W(Euir?rRhOPm-p@)Wn9OZ)K+Y+*>hS_!yw7hGSx5{ zNTgaAT9~CKnphZ_C7UOwr6#8trI{KSrdTGLrkW>i&cF7RnPvZmHH#-_+zJrTNoh6R zTkf1#9#@8 zsSJh;$xv1*g9VUh!C(dyO=K_uvW$T2WCn8}P6LX8NFyLNWiSA$O9ARi1hP|s@`;;w IKX7FR0Kj2VP5=M^ delta 238 zcmZoT!Q60yc|r%vP2X9sH}*W(EpR$B+b?k+yTis6j0uyxY7cI%*>hS_!_dgc)YQ|_-A~D&>IK?ugokgGdepbXWR-9=&dU{ zA9`=4$2yKxJZtK>#3!G))uaFwd;t>#sSddq7#Qxoa@Hbyzp~9)x0zV|4H=Ap&=d#_ z87zQgB9Jx)vy&K7fg*_v$v}Byh7=%91d4#fK&q1&%z+}w3?@LB29z-Xid!-mZ{GdD Gl^Fm4rA+q# diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll index a6fb2cb90e414871a067498541c4d4bd74a47d87..022b7d1e67d2c08dd854b0e43740811a14dd212f 100755 GIT binary patch literal 64512 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 diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 2f69d43af40..990989327cb 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -18,7 +18,7 @@ Unit OutOfEnergy )>; public record ReducerEvent( - DateTimeOffset Timestamp, + Timestamp Timestamp, Status Status, Identity CallerIdentity, Address? CallerAddress, diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs index 4a00d705735..73426730a9b 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs @@ -17,18 +17,18 @@ public sealed partial class InitialSubscription public DatabaseUpdate DatabaseUpdate; [DataMember(Name = "request_id")] public uint RequestId; - [DataMember(Name = "total_host_execution_duration_micros")] - public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "total_host_execution_duration")] + public SpacetimeDB.TimeDuration TotalHostExecutionDuration; public InitialSubscription( DatabaseUpdate DatabaseUpdate, uint RequestId, - ulong TotalHostExecutionDurationMicros + SpacetimeDB.TimeDuration TotalHostExecutionDuration ) { this.DatabaseUpdate = DatabaseUpdate; this.RequestId = RequestId; - this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.TotalHostExecutionDuration = TotalHostExecutionDuration; } public InitialSubscription() diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs index 9ec9fd19723..688147ed160 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs @@ -19,20 +19,20 @@ public sealed partial class OneOffQueryResponse public string? Error; [DataMember(Name = "tables")] public System.Collections.Generic.List Tables; - [DataMember(Name = "total_host_execution_duration_micros")] - public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "total_host_execution_duration")] + public SpacetimeDB.TimeDuration TotalHostExecutionDuration; public OneOffQueryResponse( System.Collections.Generic.List MessageId, string? Error, System.Collections.Generic.List Tables, - ulong TotalHostExecutionDurationMicros + SpacetimeDB.TimeDuration TotalHostExecutionDuration ) { this.MessageId = MessageId; this.Error = Error; this.Tables = Tables; - this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.TotalHostExecutionDuration = TotalHostExecutionDuration; } public OneOffQueryResponse() diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs.meta index 392536c1eac..bb8522b25fd 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs.meta +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs.meta @@ -2,10 +2,10 @@ fileFormatVersion: 2 guid: 5839c57344b5d64e74c4564ffb7d92f7 MonoImporter: externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs.meta index b343d062d18..e5e4ca61563 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs.meta +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs.meta @@ -2,10 +2,10 @@ fileFormatVersion: 2 guid: c99e14f23b6036cd7de97be2069db72e MonoImporter: externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs.meta index 378eac7159d..ab83d2e037e 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs.meta +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs.meta @@ -2,10 +2,10 @@ fileFormatVersion: 2 guid: 3a92d1b128da222eb02e454367e4975b MonoImporter: externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs.meta index 73c9c34fe2c..5a014bebb46 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs.meta +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs.meta @@ -2,10 +2,10 @@ fileFormatVersion: 2 guid: c60bb4c52fbbd0232497865777d0d702 MonoImporter: externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs.meta index fba50ff6816..2b721f03203 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs.meta +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs.meta @@ -2,10 +2,10 @@ fileFormatVersion: 2 guid: 2ddffc0192386ada178b6d140274dfc8 MonoImporter: externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs deleted file mode 100644 index 5f5a954d77d..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs +++ /dev/null @@ -1,28 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public sealed partial class Timestamp - { - [DataMember(Name = "microseconds")] - public ulong Microseconds; - - public Timestamp(ulong Microseconds) - { - this.Microseconds = Microseconds; - } - - public Timestamp() - { - } - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs.meta deleted file mode 100644 index 94af80d6c6e..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 145b8ed3026f531488ee5400d4cb8894 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs index 5969357fb6c..b9e822f1a58 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs @@ -16,7 +16,7 @@ public sealed partial class TransactionUpdate [DataMember(Name = "status")] public UpdateStatus Status; [DataMember(Name = "timestamp")] - public Timestamp Timestamp; + public SpacetimeDB.Timestamp Timestamp; [DataMember(Name = "caller_identity")] public SpacetimeDB.Identity CallerIdentity; [DataMember(Name = "caller_address")] @@ -25,17 +25,17 @@ public sealed partial class TransactionUpdate public ReducerCallInfo ReducerCall; [DataMember(Name = "energy_quanta_used")] public EnergyQuanta EnergyQuantaUsed; - [DataMember(Name = "host_execution_duration_micros")] - public ulong HostExecutionDurationMicros; + [DataMember(Name = "total_host_execution_duration")] + public SpacetimeDB.TimeDuration TotalHostExecutionDuration; public TransactionUpdate( UpdateStatus Status, - Timestamp Timestamp, + SpacetimeDB.Timestamp Timestamp, SpacetimeDB.Identity CallerIdentity, SpacetimeDB.Address CallerAddress, ReducerCallInfo ReducerCall, EnergyQuanta EnergyQuantaUsed, - ulong HostExecutionDurationMicros + SpacetimeDB.TimeDuration TotalHostExecutionDuration ) { this.Status = Status; @@ -44,13 +44,12 @@ ulong HostExecutionDurationMicros this.CallerAddress = CallerAddress; this.ReducerCall = ReducerCall; this.EnergyQuantaUsed = EnergyQuantaUsed; - this.HostExecutionDurationMicros = HostExecutionDurationMicros; + this.TotalHostExecutionDuration = TotalHostExecutionDuration; } public TransactionUpdate() { this.Status = null!; - this.Timestamp = new(); this.ReducerCall = new(); this.EnergyQuantaUsed = new(); } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs.meta index c825ecddb7a..fd0257faea4 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs.meta +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs.meta @@ -2,10 +2,10 @@ fileFormatVersion: 2 guid: afdaf1dde5b73fdb44b7b0e967166a43 MonoImporter: externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs.meta index 668cf4783d3..6879233963b 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs.meta +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs.meta @@ -2,10 +2,10 @@ fileFormatVersion: 2 guid: a958bf68ea209aafda05cf9222cb3639 MonoImporter: externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 852b536ee95..53cf1a9cd61 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -601,7 +601,7 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) try { reducerEvent = new( - DateTimeOffset.FromUnixTimeMilliseconds((long)transactionUpdate.Timestamp.Microseconds / 1000), + (DateTimeOffset)transactionUpdate.Timestamp, transactionUpdate.Status switch { UpdateStatus.Committed => Committed, @@ -908,7 +908,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) { var reducer = transactionUpdate.ReducerCall.ReducerName; stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdate)},reducer={reducer}"); - var hostDuration = TimeSpan.FromMilliseconds(transactionUpdate.HostExecutionDurationMicros / 1000.0d); + var hostDuration = (TimeSpan)transactionUpdate.TotalHostExecutionDuration; stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); var callerIdentity = transactionUpdate.CallerIdentity; if (callerIdentity == Identity) diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index bbedc297919..2fb76cae07b 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -25,7 +25,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_1, + Timestamp: 1718487763059031, Status: { $type: Status.Committed }, @@ -51,7 +51,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_2, + Timestamp: 1718487768057579, Status: { $type: Status.Committed }, @@ -82,7 +82,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_2, + Timestamp: 1718487768057579, Status: { $type: Status.Committed }, @@ -104,7 +104,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_3, + Timestamp: 1718487775346381, Status: { $type: Status.Committed }, @@ -131,7 +131,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_3, + Timestamp: 1718487775346381, Status: { $type: Status.Committed }, @@ -153,7 +153,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_4, + Timestamp: 1718487777307855, Status: { $type: Status.Committed }, @@ -184,7 +184,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_4, + Timestamp: 1718487777307855, Status: { $type: Status.Committed }, @@ -206,7 +206,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_5, + Timestamp: 1718487783175083, Status: { $type: Status.Committed }, @@ -233,7 +233,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_5, + Timestamp: 1718487783175083, Status: { $type: Status.Committed }, @@ -255,7 +255,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_6, + Timestamp: 1718487787645364, Status: { $type: Status.Committed }, @@ -282,7 +282,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_6, + Timestamp: 1718487787645364, Status: { $type: Status.Committed }, @@ -304,7 +304,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_7, + Timestamp: 1718487791901504, Status: { $type: Status.Committed }, @@ -336,7 +336,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_8, + Timestamp: 1718487794937841, Status: { $type: Status.Committed }, @@ -363,7 +363,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_8, + Timestamp: 1718487794937841, Status: { $type: Status.Committed }, diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index 094d87e3f15..86207acc31d 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -25,7 +25,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_1, + Timestamp: 1718487763059031, Status: { $type: Status.Committed }, @@ -51,7 +51,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_2, + Timestamp: 1718487768057579, Status: { $type: Status.Committed }, @@ -82,7 +82,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_2, + Timestamp: 1718487768057579, Status: { $type: Status.Committed }, @@ -104,7 +104,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_3, + Timestamp: 1718487775346381, Status: { $type: Status.Committed }, @@ -131,7 +131,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_3, + Timestamp: 1718487775346381, Status: { $type: Status.Committed }, @@ -153,7 +153,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_4, + Timestamp: 1718487777307855, Status: { $type: Status.Committed }, @@ -184,7 +184,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_4, + Timestamp: 1718487777307855, Status: { $type: Status.Committed }, @@ -206,7 +206,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_5, + Timestamp: 1718487783175083, Status: { $type: Status.Committed }, @@ -233,7 +233,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_5, + Timestamp: 1718487783175083, Status: { $type: Status.Committed }, @@ -255,7 +255,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_6, + Timestamp: 1718487787645364, Status: { $type: Status.Committed }, @@ -282,7 +282,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_6, + Timestamp: 1718487787645364, Status: { $type: Status.Committed }, @@ -304,7 +304,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_7, + Timestamp: 1718487791901504, Status: { $type: Status.Committed }, @@ -336,7 +336,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_8, + Timestamp: 1718487794937841, Status: { $type: Status.Committed }, @@ -363,7 +363,7 @@ Event: { $type: Event.Reducer, ReducerEvent: { - Timestamp: DateTimeOffset_8, + Timestamp: 1718487794937841, Status: { $type: Status.Committed }, diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 532fe22c8ed..961fa0d1306 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -46,7 +46,7 @@ class TimestampConverter : WriteOnlyJsonConverter { public override void Write(VerifyJsonWriter writer, Timestamp timestamp) { - writer.WriteValue(timestamp.Microseconds); + writer.WriteValue(timestamp.MicrosecondsSinceUnixEpoch); } } @@ -106,12 +106,12 @@ private static ServerMessage.IdentityToken SampleId(string identity, string toke private static ServerMessage.InitialSubscription SampleLegacyInitialSubscription( uint requestId, - ulong hostExecutionDuration, + long hostExecutionDuration, List updates ) => new(new() { RequestId = requestId, - TotalHostExecutionDurationMicros = hostExecutionDuration, + TotalHostExecutionDuration = new TimeDuration(hostExecutionDuration), DatabaseUpdate = new DatabaseUpdate { Tables = updates @@ -174,21 +174,21 @@ ulong hostExecutionDuration }); private static ServerMessage.TransactionUpdate SampleTransactionUpdate( - ulong timestamp, + long microsecondsSinceUnixEpoch, string callerIdentity, string callerAddress, uint requestId, string reducerName, ulong energyQuantaUsed, - ulong hostExecutionDuration, + long hostExecutionDurationMicros, List updates, byte[]? args ) => new(new() { - Timestamp = new Timestamp { Microseconds = timestamp }, + Timestamp = new Timestamp { MicrosecondsSinceUnixEpoch = microsecondsSinceUnixEpoch }, CallerIdentity = Identity.From(Convert.FromBase64String(callerIdentity)), CallerAddress = Address.From(Convert.FromBase64String(callerAddress)) ?? throw new InvalidDataException("callerAddress"), - HostExecutionDurationMicros = hostExecutionDuration, + TotalHostExecutionDuration = new TimeDuration(hostExecutionDurationMicros), EnergyQuantaUsed = new() { Quanta = new U128(0, energyQuantaUsed), @@ -272,10 +272,10 @@ private static TableUpdate SampleUserUpdate(string identity, string? oldName, st }]); - private static Message SampleMessage(string identity, ulong sent, string text) => new() + private static Message SampleMessage(string identity, long sentMicrosecondsSinceUnixEpoch, string text) => new() { Sender = Identity.From(Convert.FromBase64String(identity)), - Sent = sent, + Sent = new Timestamp(sentMicrosecondsSinceUnixEpoch), Text = text }; diff --git a/sdks/csharp/tools~/gen-client-api.sh b/sdks/csharp/tools~/gen-client-api.sh index 0d840e834a9..ba169fd518d 100755 --- a/sdks/csharp/tools~/gen-client-api.sh +++ b/sdks/csharp/tools~/gen-client-api.sh @@ -1,7 +1,10 @@ +#!/bin/bash + set -ueo pipefail STDB_PATH="$1" SDK_PATH="$(dirname "$0")/.." +SDK_PATH="$(realpath "$SDK_PATH")" cargo run --manifest-path $STDB_PATH/crates/client-api-messages/Cargo.toml --example get_ws_schema | cargo run --manifest-path $STDB_PATH/crates/cli/Cargo.toml -- generate -l csharp --namespace SpacetimeDB.ClientApi \ diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index 9954ea7d72c..2e50e092ed7 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit 9954ea7d72c6cc70820710085d4d93612f849652 +Subproject commit 2e50e092ed7323b6ca5ed9e7b194330e8aedc60b From 9f58828caa72a3a66db001350c393d0aebdd597e Mon Sep 17 00:00:00 2001 From: james gilles Date: Fri, 7 Feb 2025 17:03:55 -0500 Subject: [PATCH 172/223] Rework event contexts in C# (#240) ## Description of Changes https://github.com/clockworklabs/SpacetimeDB/pull/2226 ## API - [x] This is an API breaking change to the SDK callbacks are better ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2226 ## Testsuite SpacetimeDB branch name: jgilles/csharp-better-events ## Testing - [x] quickstart - [x] blackholio --- .../examples~/quickstart/client/Program.cs | 26 +-- .../Reducers/IdentityConnected.g.cs | 4 +- .../Reducers/IdentityDisconnected.g.cs | 4 +- .../module_bindings/Reducers/SendMessage.g.cs | 4 +- .../module_bindings/Reducers/SetName.g.cs | 4 +- .../module_bindings/SpacetimeDBClient.g.cs | 76 ++++++- sdks/csharp/src/Event.cs | 98 +++++--- sdks/csharp/src/RemoteTablesBase.cs | 1 - sdks/csharp/src/SpacetimeDBClient.cs | 33 ++- ...p_dumpName=LegacySubscribeAll.verified.txt | 210 ++++++++++-------- ...ump_dumpName=SubscribeApplied.verified.txt | 210 ++++++++++-------- sdks/csharp/unity-tests~ | 2 +- 12 files changed, 416 insertions(+), 256 deletions(-) diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index f82d8f87e69..7c4a891d8c4 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -104,27 +104,21 @@ void Message_OnInsert(EventContext ctx, Message insertedValue) } } -void Reducer_OnSetNameEvent(EventContext ctx, string name) +void Reducer_OnSetNameEvent(ReducerEventContext ctx, string name) { - if (ctx.Event is Event.Reducer reducer) + var e = ctx.Event; + if (e.CallerIdentity == local_identity && e.Status is Status.Failed(var error)) { - var e = reducer.ReducerEvent; - if (e.CallerIdentity == local_identity && e.Status is Status.Failed(var error)) - { - Console.Write($"Failed to change name to {name}: {error}"); - } + Console.Write($"Failed to change name to {name}: {error}"); } } -void Reducer_OnSendMessageEvent(EventContext ctx, string text) +void Reducer_OnSendMessageEvent(ReducerEventContext ctx, string text) { - if (ctx.Event is Event.Reducer reducer) + var e = ctx.Event; + if (e.CallerIdentity == local_identity && e.Status is Status.Failed(var error)) { - var e = reducer.ReducerEvent; - if (e.CallerIdentity == local_identity && e.Status is Status.Failed(var error)) - { - Console.Write($"Failed to send message {text}: {error}"); - } + Console.Write($"Failed to send message {text}: {error}"); } } @@ -134,7 +128,7 @@ void OnConnect(DbConnection conn, Identity identity, string authToken) AuthToken.SaveToken(authToken); var subscriptions = 0; - SubscriptionBuilder.Callback waitForSubscriptions = (EventContext ctx) => + Action waitForSubscriptions = (SubscriptionEventContext ctx) => { // Note: callbacks are always invoked on the main thread, so you don't need to // worry about thread synchronization or anything like that. @@ -176,7 +170,7 @@ void PrintMessagesInOrder(RemoteTables tables) } } -void OnSubscriptionApplied(EventContext ctx) +void OnSubscriptionApplied(SubscriptionEventContext ctx) { Console.WriteLine("Connected"); PrintMessagesInOrder(ctx.Db); diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs index 89ef3a69fdc..688edfb2eb3 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs @@ -12,10 +12,10 @@ namespace SpacetimeDB.Types { public sealed partial class RemoteReducers : RemoteBase { - public delegate void IdentityConnectedHandler(EventContext ctx); + public delegate void IdentityConnectedHandler(ReducerEventContext ctx); public event IdentityConnectedHandler? OnIdentityConnected; - public bool InvokeIdentityConnected(EventContext ctx, Reducer.IdentityConnected args) + public bool InvokeIdentityConnected(ReducerEventContext ctx, Reducer.IdentityConnected args) { if (OnIdentityConnected == null) return false; OnIdentityConnected( diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs index 8f3d051a2da..b44f2ed76a6 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs @@ -12,10 +12,10 @@ namespace SpacetimeDB.Types { public sealed partial class RemoteReducers : RemoteBase { - public delegate void IdentityDisconnectedHandler(EventContext ctx); + public delegate void IdentityDisconnectedHandler(ReducerEventContext ctx); public event IdentityDisconnectedHandler? OnIdentityDisconnected; - public bool InvokeIdentityDisconnected(EventContext ctx, Reducer.IdentityDisconnected args) + public bool InvokeIdentityDisconnected(ReducerEventContext ctx, Reducer.IdentityDisconnected args) { if (OnIdentityDisconnected == null) return false; OnIdentityDisconnected( diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs index 974e9a07c78..3a198619ec2 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs @@ -12,7 +12,7 @@ namespace SpacetimeDB.Types { public sealed partial class RemoteReducers : RemoteBase { - public delegate void SendMessageHandler(EventContext ctx, string text); + public delegate void SendMessageHandler(ReducerEventContext ctx, string text); public event SendMessageHandler? OnSendMessage; public void SendMessage(string text) @@ -20,7 +20,7 @@ public void SendMessage(string text) conn.InternalCallReducer(new Reducer.SendMessage(text), this.SetCallReducerFlags.SendMessageFlags); } - public bool InvokeSendMessage(EventContext ctx, Reducer.SendMessage args) + public bool InvokeSendMessage(ReducerEventContext ctx, Reducer.SendMessage args) { if (OnSendMessage == null) return false; OnSendMessage( diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs index 6d7e2356e49..cd0429e3ecb 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs @@ -12,7 +12,7 @@ namespace SpacetimeDB.Types { public sealed partial class RemoteReducers : RemoteBase { - public delegate void SetNameHandler(EventContext ctx, string name); + public delegate void SetNameHandler(ReducerEventContext ctx, string name); public event SetNameHandler? OnSetName; public void SetName(string name) @@ -20,7 +20,7 @@ public void SetName(string name) conn.InternalCallReducer(new Reducer.SetName(name), this.SetCallReducerFlags.SetNameFlags); } - public bool InvokeSetName(EventContext ctx, Reducer.SetName args) + public bool InvokeSetName(ReducerEventContext ctx, Reducer.SetName args) { if (OnSetName == null) return false; OnSetName( diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs index a6bef070858..97c69fa3033 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs @@ -26,6 +26,7 @@ public RemoteTables(DbConnection conn) } public sealed partial class SetReducerFlags { } + public sealed class EventContext : IEventContext { private readonly DbConnection conn; @@ -35,13 +36,67 @@ public sealed class EventContext : IEventContext public RemoteReducers Reducers => conn.Reducers; public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - internal EventContext(DbConnection conn, Event reducerEvent) + internal EventContext(DbConnection conn, Event Event) + { + this.conn = conn; + this.Event = Event; + } + } + + public sealed class ReducerEventContext : IReducerEventContext + { + private readonly DbConnection conn; + public readonly ReducerEvent Event; + + public RemoteTables Db => conn.Db; + public RemoteReducers Reducers => conn.Reducers; + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + + internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) { this.conn = conn; Event = reducerEvent; } } + public sealed class ErrorContext : IErrorContext + { + private readonly DbConnection conn; + public readonly Exception Event; + Exception IErrorContext.Event + { + get + { + return Event; + } + } + + public RemoteTables Db => conn.Db; + public RemoteReducers Reducers => conn.Reducers; + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + public Exception Error => Event; + + internal ErrorContext(DbConnection conn, Exception error) + { + this.conn = conn; + Event = error; + } + } + + public sealed class SubscriptionEventContext : ISubscriptionEventContext + { + private readonly DbConnection conn; + + public RemoteTables Db => conn.Db; + public RemoteReducers Reducers => conn.Reducers; + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + + internal SubscriptionEventContext(DbConnection conn) + { + this.conn = conn; + } + } + public abstract partial class Reducer { private Reducer() { } @@ -75,12 +130,21 @@ protected override Reducer ToReducer(TransactionUpdate update) }; } - protected override IEventContext ToEventContext(Event reducerEvent) => - new EventContext(this, reducerEvent); + protected override IEventContext ToEventContext(Event Event) => + new EventContext(this, Event); + + protected override IReducerEventContext ToReducerEventContext(ReducerEvent reducerEvent) => + new ReducerEventContext(this, reducerEvent); + + protected override ISubscriptionEventContext MakeSubscriptionEventContext() => + new SubscriptionEventContext(this); + + protected override IErrorContext ToErrorContext(Exception exception) => + new ErrorContext(this, exception); - protected override bool Dispatch(IEventContext context, Reducer reducer) + protected override bool Dispatch(IReducerEventContext context, Reducer reducer) { - var eventContext = (EventContext)context; + var eventContext = (ReducerEventContext)context; return reducer switch { Reducer.IdentityConnected args => Reducers.InvokeIdentityConnected(eventContext, args), @@ -92,6 +156,6 @@ protected override bool Dispatch(IEventContext context, Reducer reducer) }; } - public SubscriptionBuilder SubscriptionBuilder() => new(this); + public SubscriptionBuilder SubscriptionBuilder() => new(this); } } diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 990989327cb..5f9fd84fb15 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -3,7 +3,27 @@ namespace SpacetimeDB { - public interface IEventContext { } + public interface IEventContext + { + + } + + public interface IReducerEventContext + { + + } + + public interface ISubscriptionEventContext + { + + } + + public interface IErrorContext + { + public Exception Event { get; } + } + + public interface IReducerArgs : BSATN.IStructuralReadWrite { @@ -38,46 +58,57 @@ public record UnknownTransaction : Event; } // TODO: Move those classes into EventContext, so that we wouldn't need repetitive generics. - public sealed class SubscriptionBuilder - where EventContext : IEventContext + public sealed class SubscriptionBuilder + where SubscriptionEventContext : ISubscriptionEventContext + where ErrorContext : IErrorContext { private readonly IDbConnection conn; - public delegate void Callback(EventContext ctx); - private event Callback? Applied; - private event Callback? Error; + + private event Action? Applied; + private event Action? Error; public SubscriptionBuilder(IDbConnection conn) { this.conn = conn; } - public SubscriptionBuilder OnApplied(Callback callback) + public SubscriptionBuilder OnApplied( + Action callback + ) { Applied += callback; return this; } - public SubscriptionBuilder OnError(Callback callback) + public SubscriptionBuilder OnError( + Action callback + ) { Error += callback; return this; } - public SubscriptionHandle Subscribe(string querySql) => new(conn, Applied, Error, querySql); + public SubscriptionHandle Subscribe( + string querySql + ) => new(conn, Applied, Error, querySql); public void SubscribeToAllTables() { // Make sure we use the legacy handle constructor here, even though there's only 1 query. // We drop the error handler, since it can't be called for legacy subscriptions. - new SubscriptionHandle(conn, Applied, new string[] { "SELECT * FROM *" }); + new SubscriptionHandle( + conn, + Applied, + new string[] { "SELECT * FROM *" } + ); } } public interface ISubscriptionHandle { - void OnApplied(IEventContext ctx, SubscriptionAppliedType state); - void OnError(IEventContext ctx); - void OnEnded(IEventContext ctx); + void OnApplied(ISubscriptionEventContext ctx, SubscriptionAppliedType state); + void OnError(IErrorContext ctx); + void OnEnded(ISubscriptionEventContext ctx); } /// @@ -105,20 +136,18 @@ public partial record SubscriptionAppliedType : TaggedEnum<( /// /// [Type] - public partial record SubscriptionState : TaggedEnum<( - Unit Pending, - QueryId Active, - Unit LegacyActive, - Unit Ended)> + public partial record SubscriptionState + : TaggedEnum<(Unit Pending, QueryId Active, Unit LegacyActive, Unit Ended)> { } - public class SubscriptionHandle : ISubscriptionHandle - where EventContext : IEventContext + public class SubscriptionHandle : ISubscriptionHandle + where SubscriptionEventContext : ISubscriptionEventContext + where ErrorContext : IErrorContext { private readonly IDbConnection conn; - private readonly SubscriptionBuilder.Callback? onApplied; - private readonly SubscriptionBuilder.Callback? onError; - private SubscriptionBuilder.Callback? onEnded; + private readonly Action? onApplied; + private readonly Action? onError; + private Action? onEnded; private SubscriptionState state; @@ -144,7 +173,7 @@ public bool IsActive } } - void ISubscriptionHandle.OnApplied(IEventContext ctx, SubscriptionAppliedType type) + void ISubscriptionHandle.OnApplied(ISubscriptionEventContext ctx, SubscriptionAppliedType type) { if (type is SubscriptionAppliedType.Active active) { @@ -154,19 +183,19 @@ void ISubscriptionHandle.OnApplied(IEventContext ctx, SubscriptionAppliedType ty { state = new SubscriptionState.LegacyActive(new()); } - onApplied?.Invoke((EventContext)ctx); + onApplied?.Invoke((SubscriptionEventContext)ctx); } - void ISubscriptionHandle.OnEnded(IEventContext ctx) + void ISubscriptionHandle.OnEnded(ISubscriptionEventContext ctx) { state = new SubscriptionState.Ended(new()); - onEnded?.Invoke((EventContext)ctx); + onEnded?.Invoke((SubscriptionEventContext)ctx); } - void ISubscriptionHandle.OnError(IEventContext ctx) + void ISubscriptionHandle.OnError(IErrorContext ctx) { state = new SubscriptionState.Ended(new()); - onError?.Invoke((EventContext)ctx); + onError?.Invoke((ErrorContext)ctx, ctx.Event); } /// @@ -176,7 +205,7 @@ void ISubscriptionHandle.OnError(IEventContext ctx) /// /// /// - internal SubscriptionHandle(IDbConnection conn, SubscriptionBuilder.Callback? onApplied, string[] querySqls) + internal SubscriptionHandle(IDbConnection conn, Action? onApplied, string[] querySqls) { state = new SubscriptionState.Pending(new()); this.conn = conn; @@ -191,7 +220,12 @@ internal SubscriptionHandle(IDbConnection conn, SubscriptionBuilder /// /// - internal SubscriptionHandle(IDbConnection conn, SubscriptionBuilder.Callback? onApplied, SubscriptionBuilder.Callback? onError, string querySql) + internal SubscriptionHandle( + IDbConnection conn, + Action? onApplied, + Action? onError, + string querySql + ) { state = new SubscriptionState.Pending(new()); this.onApplied = onApplied; @@ -214,7 +248,7 @@ public void Unsubscribe() /// Unsubscribe from the query controlled by this subscription handle, /// and call onEnded when its rows are removed from the client cache. /// - public void UnsubscribeThen(SubscriptionBuilder.Callback? onEnded) + public void UnsubscribeThen(Action? onEnded) { if (state is not SubscriptionState.Active) { diff --git a/sdks/csharp/src/RemoteTablesBase.cs b/sdks/csharp/src/RemoteTablesBase.cs index 1403fe98ab5..a1a6e2b64c4 100644 --- a/sdks/csharp/src/RemoteTablesBase.cs +++ b/sdks/csharp/src/RemoteTablesBase.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; namespace SpacetimeDB { diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 53cf1a9cd61..30a20e12de6 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -182,7 +182,10 @@ struct DbOp public abstract Tables Db { get; } protected abstract Reducer ToReducer(TransactionUpdate update); - protected abstract IEventContext ToEventContext(Event reducerEvent); + protected abstract IEventContext ToEventContext(Event Event); + protected abstract IReducerEventContext ToReducerEventContext(ReducerEvent reducerEvent); + protected abstract ISubscriptionEventContext MakeSubscriptionEventContext(); + protected abstract IErrorContext ToErrorContext(Exception errorContext); private readonly Dictionary> waitingOneOffQueries = new(); @@ -788,7 +791,7 @@ private void OnMessageProcessCompleteUpdate(IEventContext eventContext, List.SubscribeApplied()); - OnMessageProcessCompleteUpdate(eventContext, dbOps); + var eventContext = MakeSubscriptionEventContext(); + var legacyEventContext = ToEventContext(new Event.SubscribeApplied()); + OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); if (legacySubscriptions.TryGetValue(initialSubscription.RequestId, out var subscription)) { try @@ -823,8 +827,9 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) { stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.SubscribeApplied)}"); stats.SubscriptionRequestTracker.FinishTrackingRequest(subscribeApplied.RequestId); - var eventContext = ToEventContext(new Event.SubscribeApplied()); - OnMessageProcessCompleteUpdate(eventContext, dbOps); + var eventContext = MakeSubscriptionEventContext(); + var legacyEventContext = ToEventContext(new Event.SubscribeApplied()); + OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); if (subscriptions.TryGetValue(subscribeApplied.QueryId.Id, out var subscription)) { try @@ -849,8 +854,10 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) stats.SubscriptionRequestTracker.FinishTrackingRequest(subscriptionError.RequestId.Value); } // TODO: should I use a more specific exception type here? - var eventContext = ToEventContext(new Event.SubscribeError(new Exception(subscriptionError.Error))); - OnMessageProcessCompleteUpdate(eventContext, dbOps); + var exception = new Exception(subscriptionError.Error); + var eventContext = ToErrorContext(exception); + var legacyEventContext = ToEventContext(new Event.SubscribeError(exception)); + OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); if (subscriptionError.QueryId.HasValue) { if (subscriptions.TryGetValue(subscriptionError.QueryId.Value, out var subscription)) @@ -878,8 +885,9 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) { stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.UnsubscribeApplied)}"); stats.SubscriptionRequestTracker.FinishTrackingRequest(unsubscribeApplied.RequestId); - var eventContext = ToEventContext(new Event.UnsubscribeApplied()); - OnMessageProcessCompleteUpdate(eventContext, dbOps); + var eventContext = MakeSubscriptionEventContext(); + var legacyEventContext = ToEventContext(new Event.UnsubscribeApplied()); + OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); if (subscriptions.TryGetValue(unsubscribeApplied.QueryId.Id, out var subscription)) { try @@ -927,8 +935,9 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) break; } - var eventContext = ToEventContext(new Event.Reducer(reducerEvent)); - OnMessageProcessCompleteUpdate(eventContext, dbOps); + var eventContext = ToReducerEventContext(reducerEvent); + var legacyEventContext = ToEventContext(new Event.Reducer(reducerEvent)); + OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); var reducerFound = false; try diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 2fb76cae07b..35f1947ffaf 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -80,23 +80,28 @@ }, OnSetName: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487768057579, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_1, - CallerAddress: Guid_2, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SetName, - name: A - } + Timestamp: 1718487768057579, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SetName, + name: A + } + }, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Reducers: {}, SetReducerFlags: {} }, OnInsertMessage: { @@ -129,23 +134,28 @@ }, OnSendMessage: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487775346381, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_2, - CallerAddress: Guid_1, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SendMessage, - text: Hello, A! - } + Timestamp: 1718487775346381, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Hello, A! } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 + } + }, + Reducers: {}, SetReducerFlags: {} }, OnUpdateUser: { @@ -182,23 +192,28 @@ }, OnSetName: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487777307855, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_2, - CallerAddress: Guid_1, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SetName, - name: B - } + Timestamp: 1718487777307855, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SetName, + name: B + } + }, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Reducers: {}, SetReducerFlags: {} }, OnInsertMessage: { @@ -231,23 +246,28 @@ }, OnSendMessage: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487783175083, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_1, - CallerAddress: Guid_2, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SendMessage, - text: Hello, B! - } + Timestamp: 1718487783175083, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Hello, B! + } + }, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Reducers: {}, SetReducerFlags: {} }, OnInsertMessage: { @@ -280,23 +300,28 @@ }, OnSendMessage: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487787645364, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_2, - CallerAddress: Guid_1, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SendMessage, - text: Goodbye! - } + Timestamp: 1718487787645364, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Goodbye! } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 + } + }, + Reducers: {}, SetReducerFlags: {} }, OnUpdateUser: { @@ -361,23 +386,28 @@ }, OnSendMessage: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487794937841, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_1, - CallerAddress: Guid_2, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SendMessage, - text: Goodbye! - } + Timestamp: 1718487794937841, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Goodbye! + } + }, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Reducers: {}, SetReducerFlags: {} } }, diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index 86207acc31d..0e4854380d5 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -80,23 +80,28 @@ }, OnSetName: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487768057579, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_1, - CallerAddress: Guid_2, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SetName, - name: A - } + Timestamp: 1718487768057579, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SetName, + name: A + } + }, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Reducers: {}, SetReducerFlags: {} }, OnInsertMessage: { @@ -129,23 +134,28 @@ }, OnSendMessage: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487775346381, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_2, - CallerAddress: Guid_1, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SendMessage, - text: Hello, A! - } + Timestamp: 1718487775346381, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Hello, A! } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 + } + }, + Reducers: {}, SetReducerFlags: {} }, OnUpdateUser: { @@ -182,23 +192,28 @@ }, OnSetName: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487777307855, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_2, - CallerAddress: Guid_1, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SetName, - name: B - } + Timestamp: 1718487777307855, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SetName, + name: B + } + }, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Reducers: {}, SetReducerFlags: {} }, OnInsertMessage: { @@ -231,23 +246,28 @@ }, OnSendMessage: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487783175083, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_1, - CallerAddress: Guid_2, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SendMessage, - text: Hello, B! - } + Timestamp: 1718487783175083, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Hello, B! + } + }, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Reducers: {}, SetReducerFlags: {} }, OnInsertMessage: { @@ -280,23 +300,28 @@ }, OnSendMessage: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487787645364, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_2, - CallerAddress: Guid_1, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SendMessage, - text: Goodbye! - } + Timestamp: 1718487787645364, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Goodbye! } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 + } + }, + Reducers: {}, SetReducerFlags: {} }, OnUpdateUser: { @@ -361,23 +386,28 @@ }, OnSendMessage: { Event: { - $type: Event.Reducer, - ReducerEvent: { - Timestamp: 1718487794937841, - Status: { - $type: Status.Committed - }, - CallerIdentity: Identity_1, - CallerAddress: Guid_2, - EnergyConsumed: {}, - Reducer: { - $type: Reducer.SendMessage, - text: Goodbye! - } + Timestamp: 1718487794937841, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Goodbye! + } + }, + Db: { + Message: { + Count: 4 + }, + User: { + Identity: {}, + Count: 2 } }, - Db: {Scrubbed}, - Reducers: {Scrubbed}, + Reducers: {}, SetReducerFlags: {} }, OnDeleteMessage: { diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index 2e50e092ed7..1cb15a3aa43 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit 2e50e092ed7323b6ca5ed9e7b194330e8aedc60b +Subproject commit 1cb15a3aa43a70cbe918e5a4654c3b5002cc288c From f966144f3ac78a21bc007eb5d87ac6ad8ad93c51 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:21:32 -0800 Subject: [PATCH 173/223] Update DLLs (#241) ## Description of Changes This seems to fix the unity testsuite, which otherwise is failing when pointed at master. ## API No breaking changes. ## Requires SpacetimeDB PRs None ## Testsuite This is meant to fix pointing at master. SpacetimeDB branch name: master ## Testing - [x] Unity testsuite now passes --------- Co-authored-by: Zeke Foppa --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 64512 -> 65024 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 2f0ffff19fa98a27c64b5b85fb8c835148bf6c2d..76b9eacad9df81b62ae55cef50dd2baaa5fea828 100755 GIT binary patch delta 2219 zcmZ8jeQ;A%7Qgp}lJZKW4YW=3(T}uAUmMfcgruewftId(XrWLPKM+lm2Z@v9 zjiZ&{iklp*!T+BU&d+6Oq5nKtfx9p_O$)&S!wsbHf@4@XWx+Q}%kbCEfN@ zxUDdV{;Cq`F@4PbKVuHqtFumHvJrO$9L8kTVty3Is$S*e7_06qy-q5Un=!9v9+$qQ zsYMHeaXeey$z53D^6@TQ=ISDo!>(5T48HGrZQ$AhmY$y%9;ST+Yl)5rHQcUa?@s77 zKoX7`K!LXnuo3=kfNpS>?E^zrT5mHEzHQ-A zirNe#IVKuDqBD~@=58}w%?TU5yUZ}FeA@n3X7J>M72Zu|SdkOkylc#`KPR?&m%=L~ z&Gim!fvY;WABt=mu>o$?`!(>8-Y2V==5FY?kb~ z)d|u#Z3R3=w9d}W7lo8x)9sxNe;^i)P$Q(UK#EpBt;wU*WSU81SF>R65i0Gm2ZXy! zk%mV2hh04&0k8RrG_-unrJCr_i1KN|1{SPsaM!HXX{#yqgr1V+U?ih$TF(xEy$ziM zL%Lp>Nz2;9Syv-&8w_T1cf{?0V;Zj?@P@0->En22hT(@Z3X7K)Z$w!&N32 zBFO|#Q7eULi4CXdXjd6$dt5g%qBx`Da&lmUFP!RK-UkHXx)b-yWq8r&<0Ago=iv_Y zG%7s!r{PAG>YnI=!vV;13_3?1iwj0(;te#b|eyY2fh-aS*6^SH?BpZe0q2*YFuf)D%iwkGa zgP-7A$1b@=GGpEh+sP8Fk40IW%p|shMOZJ}&J@ErzWw|?{I^&+nk<>=VUK1kQlSwm z+E0jhVRSV*j-R9t#Jk52mT7^^45gp>^&nq5QI1c(u!;6TL%vawY-9My3G2LHyzkCx zeuf8L{DCwNj+M;O7SzweY&X6*=H#OK-dG{WPhMK3*1udQ^80b^X)A6$y}Wo{J-d14 z4lKjlUau%jup||Q0j=p~^{dlGoNqwWL<7nbE^>C~!~$OQhQ;;X=m&pq8w(%&ef&T5 z2h@lDe7;<2iM9lkSS;M^kA!2J{ejTtU^qy!5{)eE=?U~iBjFapAvN{U*Czj`Urs*C zcxRVDFX$K zO_6(*NKD?Df~|72Hx=EgAs>NAZ#*Va?CZci_NXW=N ziDWF1+>-G{Gw}$d<@WBj^{X3~rDDn!B`K$R9+cN9G(o0Vk&{YarZ19=MIaVvY?5*7 zJ{vBXDhOmFJ6V{GjMgW7{QHql{RrTc7ymM~7OzZ6 z>J1-nnzg2d(yN69=oQ4MgjqACLxlPm+e|3HLevLI4ra#{(vPr(tcOZ~swRcWgTaT? Ti7TC4ING8XU;P(9)MWk{$csi# delta 2322 zcmZuz3v5$W82-;KqqEzTZL)Q1w{`1Ut}Wf#(RSTbbYsc@2SXl;R$SL!U^v?OcM72) zn*^qjqJu+FqY|6}2Mz=-J^)2Tf<{R|qiC2;G`=;_n27JkfA4J@F!tvD=lj3^c}~wc zZU39P{x@}l4~&ccKK9C{q?sMvwCfhOoHI5ltK(OI`Mgq?%onjq>;%7$^|5W7358jK zAppjo8m*Vxg?Ef)r!Rw^A@O|xL#&#F{WAQ382nBVzwoK1CN_olo4mPw2IvvX$-{u1 z{FupGs|2b9#7&=VUYx9r49(oGw?sG6+^$GFwp$Zq3{&5hpwmc*}e zp+`u(O;OmCmnpM=V2+jsH}F&Dr0`<_KU!4G?=GtojD>thnQe-rkjklj>x9Hxlpr>V zgk6WN7aNq!X+wnnRc2?a;&;8S_(W)w94jY8-$og z@$DXuXNbl3NC+{WBZe!_Df*Wr;(qd2?H5d)LWL>PA>679Icl)VEI%wFv%1aNe#>mN zR+T8xrHE2&=hY6IHL21@U2KE8B}-7-jHPKm6Yk^Pj<&uNseH<=eK(bA$X1F+Q+s#F zX2#DIUOnKB&&txraa@_!h!QwK#U(l=5LIj z7#(8qIy!jb^(1hBZ<(^4CArVroU<(x^d4X9^|1l|lJ^d_lNb3~*a3dK?wK3vn59srNXYUNLS$z4(rjB&2{R;Fm() zK%GBaA6_Dbm((rsxjm7FkWZ=)$=0(!>n6UsZ{%rUZS4YWo`>l@NWb0(x$9hU*0kRM zrtul)tbLOs>wO2NFKSNKKDO(VhOJLA^1HDy819aR?^+qdyMpt2LSd=5YlYO(91LTq zSBeKayP}b<=+d|=9A6f~o?!F5runmLro|%CQYjjYbuJIyEOkqvxD<>^z46{qG!nu{ zU5)$VTs2w{zkIaNmFfXcrFx*gt>?e-bw6IPt$8rA?TO9QZTd69XOEibKgaS>C*L~S zE?@r9;&F4_&t4S|l12_3aC@Mr)B6~h3!GcaF diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll index 022b7d1e67d2c08dd854b0e43740811a14dd212f..01099c76bab29628a758dbb62305a5866b59a272 100755 GIT binary patch literal 65024 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

    ~HqmDf_05d44{=uJ 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 Date: Sun, 9 Feb 2025 19:29:18 -0500 Subject: [PATCH 174/223] Rename `Address` to `ConnectionId` (#239) ## Description of Changes Companion to [Rename `Address` to `ConnectionId`](https://github.com/clockworklabs/SpacetimeDB/pull/2220). See that PR's description for more. Like all the SDKs, this PR does not change the SDK's behavior; the SDK still generates a connection ID locally and passes it through the HTTP API. This is not exposed to users, and can be changed in a follow-up. Also, use `/usr/bin/env bash` instead of `/bin/bash` in tools, for portability reasons. ## API - [x] This is an API breaking change to the SDK `Address` is renamed to `ConnectionId`. ## Requires SpacetimeDB PRs - https://github.com/clockworklabs/SpacetimeDB/pull/2220 - ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: phoebe/rename-address-to-connection-id ## Testing - [x] Pretty much just automated testing. - [x] @kazimuth will need to update and run Blackholio. --------- Co-authored-by: James Gilles --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 65024 -> 65024 bytes sdks/csharp/src/Event.cs | 2 +- .../SpacetimeDB/ClientApi/IdentityToken.g.cs | 8 ++--- .../ClientApi/TransactionUpdate.g.cs | 8 ++--- sdks/csharp/src/SpacetimeDBClient.cs | 6 ++-- sdks/csharp/src/WebSocket.cs | 4 +-- ...p_dumpName=LegacySubscribeAll.verified.txt | 28 +++++++++--------- ...ump_dumpName=SubscribeApplied.verified.txt | 28 +++++++++--------- sdks/csharp/tests~/SnapshotTests.cs | 6 ++-- sdks/csharp/tests~/VerifyInit.cs | 8 ++--- sdks/csharp/tools~/gen-client-api.sh | 2 +- sdks/csharp/tools~/gen-quickstart.sh | 2 +- 13 files changed, 51 insertions(+), 51 deletions(-) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 76b9eacad9df81b62ae55cef50dd2baaa5fea828..f6ccf968de6d53ba197a6064a52c8f4cc08d302a 100755 GIT binary patch delta 361 zcmZoT!Q60yc|r$^XyfcD6MJMB>n5%YXVjU@$XL(VGPw~*CTwP8lHVn8TXL7Y7>|nk zlpw2Hsm6EPHXH0YBdKnjVquhIU}9;JYHX5fYLIAAU}2NxtJr

    qrn)#y-hC@g7ph(O z6;wOOs?Ta}(uo-&*S+WWd<_9w1Os`K{ccM$CQQz{tvPwx?TX0`j1rsq?j*4I8Z)FY zSTGndBrzB;m@rrZ*{KZ1KvpV)DNrO4h*QDPkiifrlEh#Rgdjc1Kp9I0GoVUypdLdY ZJB=ZA^X><}j7$xdn*|@eXPjuj4ggPybpZeX delta 382 zcmZoT!Q60yc|r%v4I!0d6MJMBr%hZL&geLqk+Gg}&g4cQS-P2#Nq(2WJ|U%ZD=s{C zTx&6*E90|f|7L?dXC&2=EsauBQY_326D?BG42?|FOe{=*{M6(`@qiOVsLioH8|mE&{p)1 z5vWE#BR@A)KPNRYMZY}1C|f@{CqFqG#L@*a5_2+A^n(i$lT%AFb5mWM0*W%r5=&C` z3rdr6GLt7SyOm}HHFEvE`YpLHjCZ7qk9R`{~Y=w!6VvMDeLvL$N zuD)HpneR>li*GW6C4&(|DnkkoS}>R~7&0UR=@f=EAj^os6iAx@`6f{LREA`ryfH%( h5E=n7h-U#b0U~a?dG`ZfMy45-n*|@eXPjuj4gew-eNF%X diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll index 01099c76bab29628a758dbb62305a5866b59a272..6a8aa95e2a63b6b6ff325891cb23a250b1a03e87 100755 GIT binary patch delta 17708 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 AO#lD@ delta 17718 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 diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 5f9fd84fb15..6c7808d9ac3 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -41,7 +41,7 @@ public record ReducerEvent( Timestamp Timestamp, Status Status, Identity CallerIdentity, - Address? CallerAddress, + ConnectionId? CallerConnectionId, U128? EnergyConsumed, R Reducer ); diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs index 56aec6a1053..f771ea74d02 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs @@ -17,18 +17,18 @@ public sealed partial class IdentityToken public SpacetimeDB.Identity Identity; [DataMember(Name = "token")] public string Token; - [DataMember(Name = "address")] - public SpacetimeDB.Address Address; + [DataMember(Name = "connection_id")] + public SpacetimeDB.ConnectionId ConnectionId; public IdentityToken( SpacetimeDB.Identity Identity, string Token, - SpacetimeDB.Address Address + SpacetimeDB.ConnectionId ConnectionId ) { this.Identity = Identity; this.Token = Token; - this.Address = Address; + this.ConnectionId = ConnectionId; } public IdentityToken() diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs index b9e822f1a58..fb70f387cb6 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs @@ -19,8 +19,8 @@ public sealed partial class TransactionUpdate public SpacetimeDB.Timestamp Timestamp; [DataMember(Name = "caller_identity")] public SpacetimeDB.Identity CallerIdentity; - [DataMember(Name = "caller_address")] - public SpacetimeDB.Address CallerAddress; + [DataMember(Name = "caller_connection_id")] + public SpacetimeDB.ConnectionId CallerConnectionId; [DataMember(Name = "reducer_call")] public ReducerCallInfo ReducerCall; [DataMember(Name = "energy_quanta_used")] @@ -32,7 +32,7 @@ public TransactionUpdate( UpdateStatus Status, SpacetimeDB.Timestamp Timestamp, SpacetimeDB.Identity CallerIdentity, - SpacetimeDB.Address CallerAddress, + SpacetimeDB.ConnectionId CallerConnectionId, ReducerCallInfo ReducerCall, EnergyQuanta EnergyQuantaUsed, SpacetimeDB.TimeDuration TotalHostExecutionDuration @@ -41,7 +41,7 @@ SpacetimeDB.TimeDuration TotalHostExecutionDuration this.Status = Status; this.Timestamp = Timestamp; this.CallerIdentity = CallerIdentity; - this.CallerAddress = CallerAddress; + this.CallerConnectionId = CallerConnectionId; this.ReducerCall = ReducerCall; this.EnergyQuantaUsed = EnergyQuantaUsed; this.TotalHostExecutionDuration = TotalHostExecutionDuration; diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 30a20e12de6..f822c3ef0e5 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -174,7 +174,7 @@ struct DbOp [Obsolete] public event Action>? onUnhandledReducerError; - public readonly Address Address = Address.Random(); + public readonly ConnectionId ConnectionId = ConnectionId.Random(); public Identity? Identity { get; private set; } internal WebSocket webSocket; @@ -613,7 +613,7 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) _ => throw new InvalidOperationException() }, transactionUpdate.CallerIdentity, - transactionUpdate.CallerAddress, + transactionUpdate.CallerConnectionId, transactionUpdate.EnergyQuantaUsed.Quanta, ToReducer(transactionUpdate)); } @@ -705,7 +705,7 @@ void IDbConnection.Connect(string? token, string uri, string addressOrName, Comp { try { - await webSocket.Connect(token, uri, addressOrName, Address, compression, light); + await webSocket.Connect(token, uri, addressOrName, ConnectionId, compression, light); } catch (Exception e) { diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index bf65c84eed4..b07015e62e3 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -51,9 +51,9 @@ public WebSocket(ConnectOptions options) public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } - public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress, Compression compression, bool light) + public async Task Connect(string? auth, string host, string nameOrAddress, ConnectionId connectionId, Compression compression, bool light) { - var uri = $"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}&compression={compression}"; + var uri = $"{host}/database/subscribe/{nameOrAddress}?connection_id={connectionId}&compression={compression}"; if (light) { uri += "&light=true"; diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 35f1947ffaf..13d6ba31bc7 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -30,7 +30,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.IdentityConnected @@ -56,7 +56,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -85,7 +85,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -114,7 +114,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -139,7 +139,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -168,7 +168,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -197,7 +197,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -226,7 +226,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -251,7 +251,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -280,7 +280,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -305,7 +305,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -334,7 +334,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.IdentityDisconnected @@ -366,7 +366,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -391,7 +391,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index 0e4854380d5..5dc1bac55ab 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -30,7 +30,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.IdentityConnected @@ -56,7 +56,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -85,7 +85,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -114,7 +114,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -139,7 +139,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -168,7 +168,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -197,7 +197,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -226,7 +226,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -251,7 +251,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -280,7 +280,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -305,7 +305,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -334,7 +334,7 @@ $type: Status.Committed }, CallerIdentity: Identity_2, - CallerAddress: Guid_1, + CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { $type: Reducer.IdentityDisconnected @@ -366,7 +366,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -391,7 +391,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerAddress: Guid_2, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 961fa0d1306..9e322903eca 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -101,7 +101,7 @@ private static ServerMessage.IdentityToken SampleId(string identity, string toke { Identity = Identity.From(Convert.FromBase64String(identity)), Token = token, - Address = Address.From(Convert.FromBase64String(address)) ?? throw new InvalidDataException("address") + ConnectionId = ConnectionId.From(Convert.FromBase64String(address)) ?? throw new InvalidDataException("address") }); private static ServerMessage.InitialSubscription SampleLegacyInitialSubscription( @@ -176,7 +176,7 @@ ulong hostExecutionDuration private static ServerMessage.TransactionUpdate SampleTransactionUpdate( long microsecondsSinceUnixEpoch, string callerIdentity, - string callerAddress, + string callerConnectionId, uint requestId, string reducerName, ulong energyQuantaUsed, @@ -187,7 +187,7 @@ private static ServerMessage.TransactionUpdate SampleTransactionUpdate( { Timestamp = new Timestamp { MicrosecondsSinceUnixEpoch = microsecondsSinceUnixEpoch }, CallerIdentity = Identity.From(Convert.FromBase64String(callerIdentity)), - CallerAddress = Address.From(Convert.FromBase64String(callerAddress)) ?? throw new InvalidDataException("callerAddress"), + CallerConnectionId = ConnectionId.From(Convert.FromBase64String(callerConnectionId)) ?? throw new InvalidDataException("callerConnectionId"), TotalHostExecutionDuration = new TimeDuration(hostExecutionDurationMicros), EnergyQuantaUsed = new() { diff --git a/sdks/csharp/tests~/VerifyInit.cs b/sdks/csharp/tests~/VerifyInit.cs index eab677634bd..5ff8b44bc68 100644 --- a/sdks/csharp/tests~/VerifyInit.cs +++ b/sdks/csharp/tests~/VerifyInit.cs @@ -24,11 +24,11 @@ public override void Write(VerifyJsonWriter writer, Identity value) } } - class AddressConverter : WriteOnlyJsonConverter

    + class ConnectionIdConverter : WriteOnlyJsonConverter { - public override void Write(VerifyJsonWriter writer, Address value) + public override void Write(VerifyJsonWriter writer, ConnectionId value) { - // Addresses are GUIDs, which Verify scrubs automatically. + // ConnectionIdes are GUIDs, which Verify scrubs automatically. writer.WriteValue(value.ToString()); } } @@ -71,7 +71,7 @@ public static void Init() settings.Converters.AddRange( [ new IdentityConverter(), - new AddressConverter(), + new ConnectionIdConverter(), new NetworkRequestTrackerConverter() ] ); diff --git a/sdks/csharp/tools~/gen-client-api.sh b/sdks/csharp/tools~/gen-client-api.sh index ba169fd518d..b06a896e56c 100755 --- a/sdks/csharp/tools~/gen-client-api.sh +++ b/sdks/csharp/tools~/gen-client-api.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ueo pipefail diff --git a/sdks/csharp/tools~/gen-quickstart.sh b/sdks/csharp/tools~/gen-quickstart.sh index af0b12b7776..f16b9ee33f5 100755 --- a/sdks/csharp/tools~/gen-quickstart.sh +++ b/sdks/csharp/tools~/gen-quickstart.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ueo pipefail From 498b25f825959dae853a7765ad57cb7fac72b751 Mon Sep 17 00:00:00 2001 From: james gilles Date: Tue, 11 Feb 2025 13:21:06 -0500 Subject: [PATCH 175/223] Emit Event.UnknownTransaction rather than throwing on unknown reducer (#244) ## Description of Changes as described ## API no breaks ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2241 ## Testsuite SpacetimeDB branch name: jgilles/unknown_reducer ## Testing see SpacetimeDB PR --- .../examples~/quickstart/client/Program.cs | 9 --- .../module_bindings/SpacetimeDBClient.g.cs | 4 - .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 65024 -> 65024 bytes sdks/csharp/src/SpacetimeDBClient.cs | 47 ++++------- ...p_dumpName=LegacySubscribeAll.verified.txt | 65 ++++++++++------ ...ump_dumpName=SubscribeApplied.verified.txt | 73 +++++++++++------- sdks/csharp/tests~/SnapshotTests.cs | 12 +-- sdks/csharp/tools~/update-against-stdb.sh | 21 +++++ sdks/csharp/unity-tests~ | 2 +- 10 files changed, 128 insertions(+), 105 deletions(-) create mode 100644 sdks/csharp/tools~/update-against-stdb.sh diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index 7c4a891d8c4..fc48da6012f 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -37,10 +37,6 @@ void Main() conn.Reducers.OnSetName += Reducer_OnSetNameEvent; conn.Reducers.OnSendMessage += Reducer_OnSendMessageEvent; -#pragma warning disable CS0612 // Using obsolete API - conn.onUnhandledReducerError += onUnhandledReducerError; -#pragma warning restore CS0612 // Using obsolete API - // declare a threadsafe cancel token to cancel the process loop var cancellationTokenSource = new CancellationTokenSource(); @@ -176,11 +172,6 @@ void OnSubscriptionApplied(SubscriptionEventContext ctx) PrintMessagesInOrder(ctx.Db); } -void onUnhandledReducerError(ReducerEvent reducerEvent) -{ - Console.WriteLine($"Unhandled reducer error in {reducerEvent.Reducer}: {reducerEvent.Status}"); -} - void ProcessThread(DbConnection conn, CancellationToken ct) { try diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs index 97c69fa3033..4dafe2587fd 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs @@ -100,8 +100,6 @@ internal SubscriptionEventContext(DbConnection conn) public abstract partial class Reducer { private Reducer() { } - - public sealed class StdbNone : Reducer { } } public sealed class DbConnection : DbConnectionBase @@ -125,7 +123,6 @@ protected override Reducer ToReducer(TransactionUpdate update) "identity_disconnected" => BSATNHelpers.Decode(encodedArgs), "send_message" => BSATNHelpers.Decode(encodedArgs), "set_name" => BSATNHelpers.Decode(encodedArgs), - "" or "" => new Reducer.StdbNone(), var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } @@ -151,7 +148,6 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) Reducer.IdentityDisconnected args => Reducers.InvokeIdentityDisconnected(eventContext, args), Reducer.SendMessage args => Reducers.InvokeSendMessage(eventContext, args), Reducer.SetName args => Reducers.InvokeSetName(eventContext, args), - Reducer.StdbNone => true, _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index f6ccf968de6d53ba197a6064a52c8f4cc08d302a..2e6a26a457774193105fba1fcd45b10b8cfb5fa8 100755 GIT binary patch delta 2337 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 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll index 6a8aa95e2a63b6b6ff325891cb23a250b1a03e87..dcc7f4ec6b9eec1519b250be82fdddf2c6a1fc9a 100755 GIT binary patch literal 65024 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 Qmpl3rub+SZ-$~$q0sRM private UintAllocator queryIdAllocator; - /// - /// Invoked when a reducer is returned with an error and has no client-side handler. - /// - [Obsolete] - public event Action>? onUnhandledReducerError; - public readonly ConnectionId ConnectionId = ConnectionId.Random(); public Identity? Identity { get; private set; } @@ -617,9 +611,11 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) transactionUpdate.EnergyQuantaUsed.Quanta, ToReducer(transactionUpdate)); } - catch (Exception e) + catch (Exception) { - Log.Exception(e); + // Failing to parse the ReducerEvent is fine, it just means we should + // call downstream stuff with an UnknownTransaction. + // See OnProcessMessageComplete. } if (transactionUpdate.Status is UpdateStatus.Committed(var committed)) @@ -809,6 +805,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) var eventContext = MakeSubscriptionEventContext(); var legacyEventContext = ToEventContext(new Event.SubscribeApplied()); OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); + if (legacySubscriptions.TryGetValue(initialSubscription.RequestId, out var subscription)) { try @@ -929,36 +926,20 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } } - if (processed.reducerEvent is not { } reducerEvent) - { - // If we are here, an error about unknown reducer should have already been logged, so nothing to do. - break; - } - var eventContext = ToReducerEventContext(reducerEvent); - var legacyEventContext = ToEventContext(new Event.Reducer(reducerEvent)); - OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); - var reducerFound = false; - try + if (processed.reducerEvent is { } reducerEvent) { - reducerFound = Dispatch(eventContext, reducerEvent.Reducer); + var legacyEventContext = ToEventContext(new Event.Reducer(reducerEvent)); + OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); + var eventContext = ToReducerEventContext(reducerEvent); + Dispatch(eventContext, reducerEvent.Reducer); + // don't invoke OnUnhandledReducerError, that's [Obsolete]. } - catch (Exception e) - { - Log.Exception(e); - } - - if (!reducerFound && transactionUpdate.Status is UpdateStatus.Failed(var failed)) + else { - try - { - onUnhandledReducerError?.Invoke(reducerEvent); - } - catch (Exception e) - { - Log.Exception(e); - } + var legacyEventContext = ToEventContext(new Event.UnknownTransaction()); + OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); } break; } diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 13d6ba31bc7..66a6b39537b 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -19,7 +19,20 @@ online: true } }, - LogException: Unknown reducer unknown-reducer (Parameter 'Reducer'), + OnInsertUser: { + eventContext: { + Event: { + $type: Event.UnknownTransaction + }, + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} + }, + user: { + identity: Identity_2, + online: true + } + }, OnInsertUser: { eventContext: { Event: { @@ -29,7 +42,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -42,7 +55,7 @@ SetReducerFlags: {} }, user: { - identity: Identity_2, + identity: Identity_3, online: true } }, @@ -98,7 +111,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -113,7 +126,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -127,7 +140,7 @@ SetReducerFlags: {} }, message: { - sender: Identity_2, + sender: Identity_3, sent: 1718487775346381, text: Hello, A! } @@ -138,7 +151,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -152,7 +165,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -167,7 +180,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -181,11 +194,11 @@ SetReducerFlags: {} }, oldUser: { - identity: Identity_2, + identity: Identity_3, online: true }, newUser: { - identity: Identity_2, + identity: Identity_3, name: B, online: true } @@ -196,7 +209,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -210,7 +223,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -264,7 +277,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -279,7 +292,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -293,7 +306,7 @@ SetReducerFlags: {} }, message: { - sender: Identity_2, + sender: Identity_3, sent: 1718487787645364, text: Goodbye! } @@ -304,7 +317,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -318,7 +331,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -333,7 +346,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -346,12 +359,12 @@ SetReducerFlags: {} }, oldUser: { - identity: Identity_2, + identity: Identity_3, name: B, online: true }, newUser: { - identity: Identity_2, + identity: Identity_3, name: B, online: false } @@ -404,7 +417,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -420,13 +433,17 @@ }, { identity: Identity_2, + online: true + }, + { + identity: Identity_3, name: B, online: false } ], Message: [ { - sender: Identity_2, + sender: Identity_3, sent: 1718487775346381, text: Hello, A! }, @@ -436,7 +453,7 @@ text: Hello, B! }, { - sender: Identity_2, + sender: Identity_3, sent: 1718487787645364, text: Goodbye! }, diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index 5dc1bac55ab..353c6ad230c 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -19,7 +19,20 @@ online: true } }, - LogException: Unknown reducer unknown-reducer (Parameter 'Reducer'), + OnInsertUser: { + eventContext: { + Event: { + $type: Event.UnknownTransaction + }, + Db: {Scrubbed}, + Reducers: {Scrubbed}, + SetReducerFlags: {} + }, + user: { + identity: Identity_2, + online: true + } + }, OnInsertUser: { eventContext: { Event: { @@ -29,7 +42,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -42,7 +55,7 @@ SetReducerFlags: {} }, user: { - identity: Identity_2, + identity: Identity_3, online: true } }, @@ -98,7 +111,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -113,7 +126,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -127,7 +140,7 @@ SetReducerFlags: {} }, message: { - sender: Identity_2, + sender: Identity_3, sent: 1718487775346381, text: Hello, A! } @@ -138,7 +151,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -152,7 +165,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -167,7 +180,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -181,11 +194,11 @@ SetReducerFlags: {} }, oldUser: { - identity: Identity_2, + identity: Identity_3, online: true }, newUser: { - identity: Identity_2, + identity: Identity_3, name: B, online: true } @@ -196,7 +209,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -210,7 +223,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -264,7 +277,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -279,7 +292,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -293,7 +306,7 @@ SetReducerFlags: {} }, message: { - sender: Identity_2, + sender: Identity_3, sent: 1718487787645364, text: Goodbye! } @@ -304,7 +317,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -318,7 +331,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -333,7 +346,7 @@ Status: { $type: Status.Committed }, - CallerIdentity: Identity_2, + CallerIdentity: Identity_3, CallerConnectionId: Guid_1, EnergyConsumed: {}, Reducer: { @@ -346,12 +359,12 @@ SetReducerFlags: {} }, oldUser: { - identity: Identity_2, + identity: Identity_3, name: B, online: true }, newUser: { - identity: Identity_2, + identity: Identity_3, name: B, online: false } @@ -404,7 +417,7 @@ }, User: { Identity: {}, - Count: 2 + Count: 3 } }, Reducers: {}, @@ -420,7 +433,7 @@ SetReducerFlags: {} }, message: { - sender: Identity_2, + sender: Identity_3, sent: 1718487775346381, text: Hello, A! } @@ -450,7 +463,7 @@ SetReducerFlags: {} }, message: { - sender: Identity_2, + sender: Identity_3, sent: 1718487787645364, text: Goodbye! } @@ -481,7 +494,7 @@ SetReducerFlags: {} }, message: { - sender: Identity_2, + sender: Identity_3, sent: 1718487775346381, text: Hello, A! } @@ -511,7 +524,7 @@ SetReducerFlags: {} }, message: { - sender: Identity_2, + sender: Identity_3, sent: 1718487787645364, text: Goodbye! } @@ -541,6 +554,10 @@ }, { identity: Identity_2, + online: true + }, + { + identity: Identity_3, name: B, online: false } @@ -552,7 +569,7 @@ text: Goodbye! }, { - sender: Identity_2, + sender: Identity_3, sent: 1718487787645364, text: Goodbye! }, @@ -562,7 +579,7 @@ text: Hello, B! }, { - sender: Identity_2, + sender: Identity_3, sent: 1718487775346381, text: Hello, A! } diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 9e322903eca..11c2fa71b43 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -303,7 +303,9 @@ public static IEnumerable SampleDump() 1, 366, [SampleUserInsert("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true)] ), SampleTransactionUpdate(0, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "unknown-reducer", 0, 40, [], null + 0, "unknown-reducer", 0, 40, [ +SampleUserInsert("k5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true) + ], null ), SampleTransactionUpdate( 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", @@ -369,7 +371,9 @@ public static IEnumerable SampleDump() 1, 2, 277, SampleUpdate(MESSAGE_TABLE_ID, MESSAGE_TABLE_NAME, [], []) ), SampleTransactionUpdate(0, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "unknown-reducer", 0, 40, [], null + 0, "unknown-reducer", 0, 40, [ + SampleUserInsert("k5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true) + ], null ), SampleTransactionUpdate( 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", @@ -476,10 +480,6 @@ public async Task VerifySampleDump(string dumpName, ServerMessage[] sampleDumpPa } ); -#pragma warning disable CS0612 // Using obsolete API - client.onUnhandledReducerError += (exception) => - events.Add("OnUnhandledReducerError", exception); -#pragma warning restore CS0612 // Using obsolete API client.Reducers.OnSendMessage += (eventContext, _text) => events.Add("OnSendMessage", eventContext); client.Reducers.OnSetName += (eventContext, _name) => events.Add("OnSetName", eventContext); diff --git a/sdks/csharp/tools~/update-against-stdb.sh b/sdks/csharp/tools~/update-against-stdb.sh new file mode 100644 index 00000000000..7b5b556f2ab --- /dev/null +++ b/sdks/csharp/tools~/update-against-stdb.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Do everything needed to update this repo from an upstream STDB clone. + +set -ueox pipefail + +STDB_PATH="$1" +SDK_PATH="$(dirname "$0")/.." +SDK_PATH="$(realpath "$SDK_PATH")" + +"$SDK_PATH/tools~/write-nuget-config.sh" "$STDB_PATH" +"$SDK_PATH/tools~/gen-client-api.sh" "$STDB_PATH" +"$SDK_PATH/tools~/gen-quickstart.sh" "$STDB_PATH" +dotnet nuget locals all --clear +dotnet pack "$STDB_PATH/crates/bindings-csharp" +rm -rf "$SDK_PATH/packages" +dotnet pack +dotnet test +pushd "$SDK_PATH"; git checkout -- 'packages/*.meta' 'packages/**/*.meta' packages/.gitignore; popd + + diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index 1cb15a3aa43..3b4f71a2f68 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit 1cb15a3aa43a70cbe918e5a4654c3b5002cc288c +Subproject commit 3b4f71a2f6854b91554dc38597c03f88f91b4966 From c6eded9ade3196f87552eb5128cfcd681cb6bcc9 Mon Sep 17 00:00:00 2001 From: Noa Date: Tue, 11 Feb 2025 13:21:17 -0600 Subject: [PATCH 176/223] Adjust http api usage for glowup (#242) ## Description of Changes Companion PR for the http api glowup. ## API Not a breaking change; this catches us up to being compatible with a breakage introduced by - https://github.com/clockworklabs/SpacetimeDB/pull/2225. ## Requires SpacetimeDB PRs - https://github.com/clockworklabs/SpacetimeDB/pull/2225 ## Testsuite SpacetimeDB branch name: master ## Testing Existing CI passes (it was failing without this change since it couldn't connect). Co-authored-by: Zeke Foppa --- sdks/csharp/src/WebSocket.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index b07015e62e3..8b8e15e13c6 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -53,7 +53,7 @@ public WebSocket(ConnectOptions options) public async Task Connect(string? auth, string host, string nameOrAddress, ConnectionId connectionId, Compression compression, bool light) { - var uri = $"{host}/database/subscribe/{nameOrAddress}?connection_id={connectionId}&compression={compression}"; + var uri = $"{host}/v1/database/{nameOrAddress}/subscribe?connection_id={connectionId}&compression={compression}"; if (light) { uri += "&light=true"; From 076d4ecbb17043869396092c96138a96ade66798 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:42:41 -0800 Subject: [PATCH 177/223] Strip trailing `/` from URIs before connecting (#238) ## Description of Changes We were not stripping `/` from the end of URIs provided to `Connect`. We manually append `/...` to the provided addresses, so if we don't start by stripping trailing `/`s, we end up with `//` in the URI and we get errors. Addresses part of https://github.com/clockworklabs/SpacetimeDB/issues/1551. ## API No breaking changes. This fixes an error case. ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing - [x] Tested the quickstart chat client with a host containing a trailing `/` ``` # start a server, publish the module, send some input # I also updated one line in `client.csproj` to use `Net8.0` because I no longer have `Net7.0` installed $ cd examples~/quickstart/client $ dotnet run [I] SpacetimeDBClient: Connecting to ws://localhost:3000 quickstart-chat C200098E is online Connected C2007471: hello C2007471: godo C2007471: asdf $ sed -i 's/localhost:3000/localhost:3000\//' Program.cs $ dotnet run [I] SpacetimeDBClient: Connecting to ws://localhost:3000 quickstart-chat C2000601 is online Connected C2007471: hello C2007471: godo C2007471: asdf $ git diff diff --git a/examples~/quickstart/client/Program.cs b/examples~/quickstart/client/Program.cs index 9eb43b1..289e736 100644 --- a/examples~/quickstart/client/Program.cs +++ b/examples~/quickstart/client/Program.cs @@ -7,8 +7,8 @@ using System.Threading; using SpacetimeDB; using SpacetimeDB.Types; -const string HOST = "http://localhost:3000"; -const string DBNAME = "chatqs"; +const string HOST = "http://localhost:3000/"; +const string DBNAME = "quickstart-chat"; // our local client SpacetimeDB identity Identity? local_identity = null; diff --git a/examples~/quickstart/client/client.csproj b/examples~/quickstart/client/client.csproj index 48917cc..ab7ce44 100644 --- a/examples~/quickstart/client/client.csproj +++ b/examples~/quickstart/client/client.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 false disable enable ``` --------- Co-authored-by: Zeke Foppa --- sdks/csharp/src/SpacetimeDBClient.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 9fd702cb79b..a6f9e9871f7 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -693,6 +693,9 @@ void IDbConnection.Connect(string? token, string uri, string addressOrName, Comp { uri = $"ws://{uri}"; } + // Things fail surprisingly if we have a trailing slash, because we later manually append strings + // like `/foo` and then end up with `//` in the URI. + uri = uri.TrimEnd('/'); Log.Info($"SpacetimeDBClient: Connecting to {uri} {addressOrName}"); if (!IsTesting) From 03861217b3b4f83936a8fd6a530c64e7cf529f8f Mon Sep 17 00:00:00 2001 From: Noa Date: Tue, 11 Feb 2025 14:13:26 -0600 Subject: [PATCH 178/223] Switch to Bearer auth (#236) ## Description of Changes Switches to Bearer authentication, which is the more proper auth schema to use with tokens. ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs - https://github.com/clockworklabs/SpacetimeDB/pull/2181 ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master --------- Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com> Co-authored-by: rekhoff Co-authored-by: James Gilles --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 65024 -> 65024 bytes sdks/csharp/src/AuthToken.cs | 2 +- sdks/csharp/src/WebSocket.cs | 4 +--- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 2e6a26a457774193105fba1fcd45b10b8cfb5fa8..f3ebe96120fb88d80336eee7b5da484e5513364b 100755 GIT binary patch delta 238 zcmZoT!Q60yc|r$ErA_0BjXe)`3%GrEUUynK+;{47h6&BG(Kk2O>^Uu|VQy(^o@$X| zW}0GdlxmS|kz|pUn3!s4WRQ}al4x$4Vwh%TXl|5jx;g*aS7w&vrni44XWR-9=yabl z?MUtp=UEfBtN%aqsbcbpTTKd3!NXBdL7?iI6U%F_mFHOUhH)~AY|gsP#OiO(V98+0 zV9t=rV8M{WUDG)bW<4s delta 238 zcmZoT!Q60yc|r$^&+mH^H}*W(E%4^_9jzBL$ zMn)!SW(JllIy0n_G^ z{j2YKc+FhcEmqR|*JkpGTTKd3!Bdh@L6GX1rw^RGDq5Kk7+IURIqNnPtA84UC4(tL z3J{w!Br+HQp$S78gBgPXP~3V5yJm z$EDR;esf|tPR_pN+c8<>OOpar&`t&_2vp6z>51QrDYn@@OvZl?Z{GH$j@93s!IHt0 z!JHwL!Ga-$!3@Yw0rHH%{A8e55)h{`Bm!Y7gCS7d04Sdf#EC#vAhm`-Su-FB(v!?! Ky1DsREi(YnC0baRnVP00r6wCEZNBpU4l~QTBL3r(w|ou|u)O*H zoRqVO|Ky_QS$DTF7)=)W(xd<@+tf>cj24DGPozVB`AZj-Lf+rHGX`lm5iGMF-? z0I@kkB7+eSnlPj>m@yat#f=z}fH;vM8AzG}*~tvX3>H9s5>Q1VkYxc>X9|RAK#^3i LY|`fDU$x8tg(^`v diff --git a/sdks/csharp/src/AuthToken.cs b/sdks/csharp/src/AuthToken.cs index 2fce2f73d34..d02026c7776 100644 --- a/sdks/csharp/src/AuthToken.cs +++ b/sdks/csharp/src/AuthToken.cs @@ -114,7 +114,7 @@ public static void SaveToken(string token) PlayerPrefs.SetString(GetTokenKey(), token); } - public static string GetTokenKey() + private static string GetTokenKey() { var key = "spacetimedb.identity_token"; #if UNITY_EDITOR diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 8b8e15e13c6..8dc4da28da3 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -64,9 +64,7 @@ public async Task Connect(string? auth, string host, string nameOrAddress, Conne var source = new CancellationTokenSource(10000); if (!string.IsNullOrEmpty(auth)) { - var tokenBytes = Encoding.UTF8.GetBytes($"token:{auth}"); - var base64 = Convert.ToBase64String(tokenBytes); - Ws.Options.SetRequestHeader("Authorization", $"Basic {base64}"); + Ws.Options.SetRequestHeader("Authorization", $"Bearer {auth}"); } else { From b80a2b99bc3c6bc5ecdeaa8a29c3e35eef21c7c8 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 13 Feb 2025 10:29:41 -0800 Subject: [PATCH 179/223] CI - Update release branch check (#246) ## Description of Changes This updates the CI check protecting the release branch, as part of https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/226 (see that ticket for more details). Once this is merged, it will need to be cherrypicked into our release branch in order to take effect there. The check itself has also been renamed. I have already updated the branch protection rules to look for the new name. ## API No code changes. ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing The previous behavior was well-tested, and I've just changed some strings here, so I have not done further testing. It does pass on this branch though. Co-authored-by: Zeke Foppa --- sdks/csharp/.github/workflows/check-pr-base.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/.github/workflows/check-pr-base.yml b/sdks/csharp/.github/workflows/check-pr-base.yml index 73b71c27f0b..e3c164863d3 100644 --- a/sdks/csharp/.github/workflows/check-pr-base.yml +++ b/sdks/csharp/.github/workflows/check-pr-base.yml @@ -8,15 +8,15 @@ permissions: read-all jobs: check_base_ref: - name: Only release branches may merge into master + name: Release branch restriction runs-on: ubuntu-latest steps: - id: not_based_on_master if: | github.event_name == 'pull_request' && - github.event.pull_request.base.ref == 'master' && + github.event.pull_request.base.ref == 'release/latest' && ! startsWith(github.event.pull_request.head.ref, 'release/') run: | - echo 'Only `release/*` branches are allowed to merge into `master`.' - echo 'Maybe your PR should be merging into `staging`?' + echo 'Only `release/*` branches are allowed to merge into the release branch `release/latest`.' + echo 'Maybe you want to change your PR base to `master`?' exit 1 From 083531e3193c66c60fd9a2f8859c5d003810ace1 Mon Sep 17 00:00:00 2001 From: james gilles Date: Tue, 25 Feb 2025 16:24:26 -0500 Subject: [PATCH 180/223] SubscribeMulti + UnsubscribeMulti, multiplicities (#249) ## Description of Changes Add SubscribeMulti and UnsubscribeMulti from upstream. Fix unsubscribe bug found by testing against Bitcraft: Calling `UnsubscribeThen` with any (non-null) callback would result in an exception incorrectly telling the user that `Unsubscribe` had been called twice. Multiplicity support is implemented with unit tests + manual testing of quickstart-chat. Also, rows in the client cache are now looked up by primary key if available, which I suspect is going to be a large performance boost. ## API - [x] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: jgilles/final-cs-codegen-changes ## Testing *Write instructions for a test that you performed for this PR* - [x] unit tests - [ ] Working with Ryan to add a test suite. - [x] blackholio --- sdks/csharp/README.md | 2 +- .../examples~/quickstart/client/Program.cs | 29 +- .../module_bindings/SpacetimeDBClient.g.cs | 323 ++++++++++++- sdks/csharp/src/Event.cs | 133 +++--- sdks/csharp/src/MultiDictionary.cs | 434 +++++++++++++++++ sdks/csharp/src/MultiDictionary.cs.meta | 11 + .../SpacetimeDB/ClientApi/ClientMessage.g.cs | 4 +- .../SpacetimeDB/ClientApi/ServerMessage.g.cs | 4 +- .../SpacetimeDB/ClientApi/SubscribeMulti.g.cs | 40 ++ .../ClientApi/SubscribeMulti.g.cs.meta | 11 + .../ClientApi/SubscribeMultiApplied.g.cs | 44 ++ .../ClientApi/SubscribeMultiApplied.g.cs.meta | 11 + .../ClientApi/UnsubscribeMulti.g.cs | 35 ++ .../ClientApi/UnsubscribeMulti.g.cs.meta | 11 + .../ClientApi/UnsubscribeMultiApplied.g.cs | 44 ++ .../UnsubscribeMultiApplied.g.cs.meta | 11 + sdks/csharp/src/SpacetimeDBClient.cs | 449 +++++++----------- sdks/csharp/src/Table.cs | 257 +++++++--- sdks/csharp/tests~/MultiDictionaryTests.cs | 244 ++++++++++ ...p_dumpName=LegacySubscribeAll.verified.txt | 108 +++-- ...ump_dumpName=SubscribeApplied.verified.txt | 153 ++++-- sdks/csharp/tests~/SnapshotTests.cs | 24 +- sdks/csharp/tests~/tests.csproj | 1 + sdks/csharp/unity-tests~ | 2 +- 24 files changed, 1879 insertions(+), 506 deletions(-) create mode 100644 sdks/csharp/src/MultiDictionary.cs create mode 100644 sdks/csharp/src/MultiDictionary.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMulti.g.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMulti.g.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMultiApplied.g.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMultiApplied.g.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMulti.g.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMulti.g.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMultiApplied.g.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMultiApplied.g.cs.meta create mode 100644 sdks/csharp/tests~/MultiDictionaryTests.cs diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 75c5fba0f55..7bf46ba7876 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -2,7 +2,7 @@ ## Overview -This repository contains the [Unity](https://unity.com/) SDK for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. +This repository contains the C# and [Unity](https://unity.com/) SDKs for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. ## Documentation diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index fc48da6012f..4327538caa2 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -94,6 +94,7 @@ void PrintMessage(RemoteTables tables, Message message) void Message_OnInsert(EventContext ctx, Message insertedValue) { + if (ctx.Event is not Event.SubscribeApplied) { PrintMessage(ctx.Db, insertedValue); @@ -123,25 +124,15 @@ void OnConnect(DbConnection conn, Identity identity, string authToken) local_identity = identity; AuthToken.SaveToken(authToken); - var subscriptions = 0; - Action waitForSubscriptions = (SubscriptionEventContext ctx) => - { - // Note: callbacks are always invoked on the main thread, so you don't need to - // worry about thread synchronization or anything like that. - subscriptions += 1; - - if (subscriptions == 2) - { - OnSubscriptionApplied(ctx); - } - }; - - var userSubscription = conn.SubscriptionBuilder() - .OnApplied(waitForSubscriptions) - .Subscribe("SELECT * FROM user"); - var messageSubscription = conn.SubscriptionBuilder() - .OnApplied(waitForSubscriptions) - .Subscribe("SELECT * FROM message"); + var subscription = conn.SubscriptionBuilder() + .OnApplied(OnSubscriptionApplied) + .Subscribe(new string[] { + "SELECT * FROM user", + "SELECT * FROM message", + // It is legal to have redundant subscriptions. + // However, keep in mind that data will be sent over the wire multiple times, + // once for each subscriptions. This can cause slowdowns if you aren't careful. + "SELECT * FROM message" }); // You can also use SubscribeToAllTables, but it should be avoided if you have any large tables: // conn.SubscriptionBuilder().OnApplied(OnSubscriptionApplied).SubscribeToAllTables(); diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs index 4dafe2587fd..7edc469d193 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs @@ -27,14 +27,68 @@ public RemoteTables(DbConnection conn) public sealed partial class SetReducerFlags { } - public sealed class EventContext : IEventContext + public interface IRemoteDbContext : IDbContext { } + + public sealed class EventContext : IEventContext, IRemoteDbContext { private readonly DbConnection conn; + + /// + /// The event that caused this callback to run. + /// public readonly Event Event; + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; internal EventContext(DbConnection conn, Event Event) { @@ -43,14 +97,65 @@ internal EventContext(DbConnection conn, Event Event) } } - public sealed class ReducerEventContext : IReducerEventContext + public sealed class ReducerEventContext : IReducerEventContext, IRemoteDbContext { private readonly DbConnection conn; + /// + /// The reducer event that caused this callback to run. + /// public readonly ReducerEvent Event; + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) { @@ -59,9 +164,12 @@ internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEve } } - public sealed class ErrorContext : IErrorContext + public sealed class ErrorContext : IErrorContext, IRemoteDbContext { private readonly DbConnection conn; + /// + /// The Exception that caused this error callback to be run. + /// public readonly Exception Event; Exception IErrorContext.Event { @@ -71,10 +179,57 @@ Exception IErrorContext.Event } } + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - public Exception Error => Event; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; internal ErrorContext(DbConnection conn, Exception error) { @@ -83,13 +238,61 @@ internal ErrorContext(DbConnection conn, Exception error) } } - public sealed class SubscriptionEventContext : ISubscriptionEventContext + public sealed class SubscriptionEventContext : ISubscriptionEventContext, IRemoteDbContext { private readonly DbConnection conn; + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; internal SubscriptionEventContext(DbConnection conn) { @@ -97,6 +300,114 @@ internal SubscriptionEventContext(DbConnection conn) } } + /// + /// Builder-pattern constructor for subscription queries. + /// + public sealed class SubscriptionBuilder + { + private readonly IDbConnection conn; + + private event Action? Applied; + private event Action? Error; + + /// + /// Private API, use conn.SubscriptionBuilder() instead. + /// + public SubscriptionBuilder(IDbConnection conn) + { + this.conn = conn; + } + + /// + /// Register a callback to run when the subscription is applied. + /// + public SubscriptionBuilder OnApplied( + Action callback + ) + { + Applied += callback; + return this; + } + + /// + /// Register a callback to run when the subscription fails. + /// + /// Note that this callback may run either when attempting to apply the subscription, + /// in which case Self::on_applied will never run, + /// or later during the subscription's lifetime if the module's interface changes, + /// in which case Self::on_applied may have already run. + /// + public SubscriptionBuilder OnError( + Action callback + ) + { + Error += callback; + return this; + } + + /// + public SubscriptionHandle Subscribe( + string[] querySqls + ) => new(conn, Applied, Error, querySqls); + + /// + /// Subscribe to all rows from all tables. + /// + /// This method is intended as a convenience + /// for applications where client-side memory use and network bandwidth are not concerns. + /// Applications where these resources are a constraint + /// should register more precise queries via Self.Subscribe + /// in order to replicate only the subset of data which the client needs to function. + /// + /// This method should not be combined with Self.Subscribe on the same DbConnection. + /// A connection may either Self.Subscribe to particular queries, + /// or Self.SubscribeToAllTables, but not both. + /// Attempting to call Self.Subscribe + /// on a DbConnection that has previously used Self.SubscribeToAllTables, + /// or vice versa, may misbehave in any number of ways, + /// including dropping subscriptions, corrupting the client cache, or panicking. + /// + public void SubscribeToAllTables() + { + // Make sure we use the legacy handle constructor here, even though there's only 1 query. + // We drop the error handler, since it can't be called for legacy subscriptions. + new SubscriptionHandle( + conn, + Applied, + new string[] { "SELECT * FROM *" } + ); + } + } + + public sealed class SubscriptionHandle : SubscriptionHandleBase + { + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle(IDbConnection conn, Action? onApplied, string[] querySqls) : base(conn, onApplied, querySqls) + { } + + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle( + IDbConnection conn, + Action? onApplied, + Action? onError, + string[] querySqls + ) : base(conn, onApplied, onError, querySqls) + { } + } + public abstract partial class Reducer { private Reducer() { } @@ -152,6 +463,6 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) }; } - public SubscriptionBuilder SubscriptionBuilder() => new(this); + public SubscriptionBuilder SubscriptionBuilder() => new(this); } } diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 6c7808d9ac3..6ad7c74c6ce 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using SpacetimeDB.ClientApi; namespace SpacetimeDB @@ -23,7 +24,73 @@ public interface IErrorContext public Exception Event { get; } } + // The following underscores are needed to work around c#'s unified type-and-function + // namespace. + /// + /// The DbContext trait, which mediates access to a remote module. + /// + /// DbContext is implemented by DbConnection and EventContext, + /// both defined in your module-specific codegen. + /// + public interface IDbContext + { + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public DbView Db { get; } + + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers { get; } + + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags_ SetReducerFlags { get; } + + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive { get; } + + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect(); + + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder_ SubscriptionBuilder(); + + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity { get; } + + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId { get; } + } public interface IReducerArgs : BSATN.IStructuralReadWrite { @@ -57,52 +124,6 @@ public record SubscribeError(Exception Exception) : Event; public record UnknownTransaction : Event; } - // TODO: Move those classes into EventContext, so that we wouldn't need repetitive generics. - public sealed class SubscriptionBuilder - where SubscriptionEventContext : ISubscriptionEventContext - where ErrorContext : IErrorContext - { - private readonly IDbConnection conn; - - private event Action? Applied; - private event Action? Error; - - public SubscriptionBuilder(IDbConnection conn) - { - this.conn = conn; - } - - public SubscriptionBuilder OnApplied( - Action callback - ) - { - Applied += callback; - return this; - } - - public SubscriptionBuilder OnError( - Action callback - ) - { - Error += callback; - return this; - } - - public SubscriptionHandle Subscribe( - string querySql - ) => new(conn, Applied, Error, querySql); - - public void SubscribeToAllTables() - { - // Make sure we use the legacy handle constructor here, even though there's only 1 query. - // We drop the error handler, since it can't be called for legacy subscriptions. - new SubscriptionHandle( - conn, - Applied, - new string[] { "SELECT * FROM *" } - ); - } - } public interface ISubscriptionHandle { @@ -140,7 +161,7 @@ public partial record SubscriptionState : TaggedEnum<(Unit Pending, QueryId Active, Unit LegacyActive, Unit Ended)> { } - public class SubscriptionHandle : ISubscriptionHandle + public class SubscriptionHandleBase : ISubscriptionHandle where SubscriptionEventContext : ISubscriptionEventContext where ErrorContext : IErrorContext { @@ -199,13 +220,13 @@ void ISubscriptionHandle.OnError(IErrorContext ctx) } /// - /// TODO: remove this constructor once legacy subscriptions are removed. + /// Construct a legacy subscription handle. /// /// /// /// /// - internal SubscriptionHandle(IDbConnection conn, Action? onApplied, string[] querySqls) + protected SubscriptionHandleBase(IDbConnection conn, Action? onApplied, string[] querySqls) { state = new SubscriptionState.Pending(new()); this.conn = conn; @@ -220,18 +241,18 @@ internal SubscriptionHandle(IDbConnection conn, Action /// /// /// - internal SubscriptionHandle( + protected SubscriptionHandleBase( IDbConnection conn, Action? onApplied, Action? onError, - string querySql + string[] querySqls ) { state = new SubscriptionState.Pending(new()); this.onApplied = onApplied; this.onError = onError; this.conn = conn; - conn.Subscribe(this, querySql); + conn.Subscribe(this, querySqls); } /// @@ -254,11 +275,15 @@ public void UnsubscribeThen(Action? onEnded) { throw new Exception("Cannot unsubscribe from inactive subscription."); } - if (onEnded != null) + if (this.onEnded != null) { - // TODO: should we just log here instead? Do we try not to throw exceptions on the main thread? throw new Exception("Unsubscribe already called."); } + if (onEnded == null) + { + // We need to put something in there to use this as a boolean. + onEnded = (ctx) => { }; + } this.onEnded = onEnded; } } diff --git a/sdks/csharp/src/MultiDictionary.cs b/sdks/csharp/src/MultiDictionary.cs new file mode 100644 index 00000000000..1807496907e --- /dev/null +++ b/sdks/csharp/src/MultiDictionary.cs @@ -0,0 +1,434 @@ +using System; +using System.Linq; +using System.Text; +using System.Collections.Generic; +using System.Diagnostics; +using System.Data; + +namespace SpacetimeDB +{ + /// + /// A dictionary that may have multiple copies of a key-value pair. + /// Note that a particular key only maps to one value -- it is a logical error + /// to insert the same key with different values. + /// + /// + /// + internal struct MultiDictionary : IEquatable> + { + // The actual data. + readonly Dictionary RawDict; + readonly IEqualityComparer ValueComparer; + + /// + /// Construct a MultiDictionary. + /// + /// This is the only valid constructor for a Multidictionary - using the parameterless constructor + /// will result in null pointer errors. But we can't enforce this because of Unity. + /// + /// + public MultiDictionary(IEqualityComparer keyComparer, IEqualityComparer valueComparer) + { + RawDict = new(keyComparer); + ValueComparer = valueComparer; + } + + public static MultiDictionary FromEnumerable(IEnumerable> enumerable, IEqualityComparer keyComparer, IEqualityComparer valueComparer) + { + var result = new MultiDictionary(keyComparer, valueComparer); + foreach (var item in enumerable) + { + result.Add(item.Key, item.Value); + } + return result; + } + + /// + /// Return the count WITHOUT multiplicities. + /// This is mathematically unnatural, but cheap. + /// + public readonly uint CountDistinct => (uint)RawDict.Count; + + /// + /// Return the count WITH multiplicities. + /// + public readonly uint Count => RawDict.Select(item => item.Value.Multiplicity).Aggregate(0u, (a, b) => a + b); + + /// + /// Add a key-value-pair to the multidictionary. + /// If the key is already present, its associated value must satisfy + /// keyComparer.Equals(value, item.Value). + /// + /// + /// Whether the key is entirely new to the dictionary. If it was already present, we assert that the old value is equal to the new value. + public bool Add(TKey key, TValue value) + { + if (value == null) + { + throw new NullReferenceException("Null values are forbidden in multidictionary"); + } + Debug.Assert(RawDict != null); + Debug.Assert(key != null); + if (RawDict.TryGetValue(key, out var result)) + { + Debug.Assert(ValueComparer.Equals(value, result.Value), "Added key-value pair with mismatched value to existing data"); + RawDict[key] = (value, result.Multiplicity + 1); + return false; + } + else + { + RawDict[key] = (value, 1); + return true; + } + } + + /// + /// Completely clear the multidictionary. + /// + public void Clear() + { + RawDict.Clear(); + } + + /// + /// Whether the multidictionary contains any copies of an item. + /// + /// + /// + public bool Contains(KeyValuePair item) + { + if (RawDict.TryGetValue(item.Key, out var result)) + { + return ValueComparer.Equals(item.Value, result.Value); + } + return false; + } + + /// + /// Remove a key from the dictionary. + /// + /// + /// Whether the last copy of the key was removed. + public bool Remove(TKey key, out TValue row) + { + if (RawDict.TryGetValue(key, out var result)) + { + row = result.Value; + if (result.Multiplicity == 1) + { + RawDict.Remove(key); + return true; + } + else + { + RawDict[key] = (result.Value, result.Multiplicity - 1); + return false; + } + } + row = default!; // uhh, this might be null. Good thing it's an internal method? + return false; + } + + public bool Equals(MultiDictionary other) + { + foreach (var item in RawDict) + { + var (key, (value, multiplicity)) = item; + if (other.RawDict.TryGetValue(key, out var otherVM)) + { + var (otherValue, otherMultiplicity) = otherVM; + if (!(ValueComparer.Equals(value, otherValue) && multiplicity == otherMultiplicity)) + { + return false; + } + } + } + + return true; + } + + public readonly IEnumerable Values + { + get + { + + return RawDict.Select(item => item.Value.Value); + } + } + + public readonly IEnumerable> Entries + { + get + { + return RawDict.Select(item => new KeyValuePair(item.Key, item.Value.Value)); + } + } + + /// + /// Iterate the rows that will be removed when `delta` is applied. + /// + /// + /// + public readonly IEnumerable> WillRemove(MultiDictionaryDelta delta) + { + var self = this; + return delta.Entries.Where(entry => + { + var theirDelta = (int)entry.Value.Inserts - (int)entry.Value.Removes; + if (theirDelta >= 0) + { + return false; + } + if (self.RawDict.TryGetValue(entry.Key, out var mine)) + { + var resultMultiplicity = (int)mine.Multiplicity + theirDelta; + return resultMultiplicity <= 0; + } + else + { + Log.Warn($"Want to remove row with key {entry.Key}, but it doesn't exist!"); + return false; + } + }).Select(entry => new KeyValuePair(entry.Key, entry.Value.Value)); + } + + /// + /// Apply a collection of changes to a multidictionary. + /// + /// The changes to apply. + /// Will be populated with inserted KVPs. + /// Will be populated with updated KVPs. + /// Will be populated with removed KVPs. + public void Apply(MultiDictionaryDelta delta, List> wasInserted, List<(TKey Key, TValue OldValue, TValue NewValue)> wasUpdated, List> wasRemoved) + { + foreach (var (key, their) in delta.Entries) + { + var theirDelta = (int)their.Inserts - (int)their.Removes; + + if (RawDict.TryGetValue(key, out var my)) + { + var newMultiplicity = (int)my.Multiplicity + theirDelta; + if (newMultiplicity > 0) + { + if (ValueComparer.Equals(my.Value, their.Value)) + { + // Update the count, NOT dispatching an update event. + + // It sort of matters if we use my.Value or their.Value here: + // They may satisfy `Equals` but not actually have equal pointers. + // We'd prefer to keep pointers stable if they don't need to change. + // So even though my.Value and theirValue are "equal", prefer using my.Value. + RawDict[key] = (my.Value, (uint)newMultiplicity); + } + else + { + // Update the count and value, dispatching an update event. + Debug.Assert(their.Removes >= my.Multiplicity, "Row was not removed enough times in update."); + + // Here, we actually have meaningful changes, so use their value. + RawDict[key] = (their.Value, (uint)newMultiplicity); + wasUpdated.Add((key, my.Value, their.Value)); // store both the old and new values. + } + } + else // if (newMultiplicity <= 0) + { + // This is a removal. + if (newMultiplicity < 0) + { + PseudoThrow($"Internal error: Removing row with key {key} {-theirDelta} times, but it is only present {my.Multiplicity} times."); + } + + RawDict.Remove(key); + wasRemoved.Add(new(key, their.Value)); + } + } + else + { + // Key is not present in map. + if (theirDelta < 0) + { + PseudoThrow($"Internal error: Removing row with key {key} {-theirDelta} times, but it not present."); + } + else if (theirDelta == 0) + { + // Hmm. + // This is not actually a problem. + // Do nothing. + } + else if (theirDelta > 0) + { + RawDict[key] = (their.Value, (uint)theirDelta); + wasInserted.Add(new(key, their.Value)); + } + } + } + + + } + + /// + /// Raise a debug assertion failure in debug mode, otherwise just warn and keep going. + /// + /// + private void PseudoThrow(string message) + { + Log.Warn(message); + Debug.Assert(false, message); + } + + public override string ToString() + { + StringBuilder result = new(); + result.Append("SpacetimeDB.MultiDictionary { "); + foreach (var item in RawDict) + { + result.Append($"({item.Key}: {item.Value.Value}) x {item.Value.Multiplicity}, "); + } + result.Append("}"); + return result.ToString(); + } + + } + + /// + /// A bulk change to a multidictionary. Allows both adding and removing rows. + /// + /// Can be applied to a multidictionary, and also inspected before application to see + /// what rows will be deleted. (This is used for OnBeforeDelete.) + /// + /// Curiously, the order of operations applied to a MultiDictionaryDelta does not matter. + /// No matter the order of Add and Remove calls on a delta, when the Delta is applied, + /// the result will be the same, as long as the Add and Remove *counts* for each KeyValuePair are + /// the same. + /// (This means that this is a "conflict-free replicated data type", unlike MultiDictionary.) + /// (MultiDictionary would also be "conflict-free" if it didn't support Remove.) + /// + /// The delta may include value updates. + /// A value can be updated multiple times, but each update must set the result to the same value. + /// When applying a delta, if the target multidictionary has multiple copies of (key, value) pair, + /// the row must be removed exactly the correct number of times. It can be inserted an arbitrary number of times. + /// + /// When removing a row for an update, it is legal for the passed value to be equal to EITHER the old value or the new value. + /// (This is because I'm not sure what SpacetimeDB core does.) + /// + /// + /// + internal struct MultiDictionaryDelta : IEquatable> + { + /// + /// For each key, track its NEW value (or old value, but only if we have never seen the new value). + /// Also track the number of times it has been removed and inserted. + /// We keep these separate so that we can debug-assert that a KVP has been removed enough times (in case + /// there are multiple copies of the KVP in the map we get applied to.) + /// + readonly Dictionary RawDict; + + readonly IEqualityComparer ValueComparer; + + /// + /// Construct a MultiDictionaryDelta. + /// + /// This is the only valid constructor for a MultiDictionaryDelta - using the parameterless constructor + /// will result in null pointer errors. But we can't enforce this because of Unity. + /// + /// + + public MultiDictionaryDelta(IEqualityComparer keyComparer, IEqualityComparer valueComparer) + { + RawDict = new(keyComparer); + ValueComparer = valueComparer; + } + + /// + /// Add a key-value-pair to the multidictionary. + /// If the key is already present, its associated value must satisfy + /// keyComparer.Equals(value, item.Value). + /// + /// + public void Add(TKey key, TValue value) + { + if (value == null) + { + throw new NullReferenceException("Null values are forbidden in multidictionary"); + } + Debug.Assert(RawDict != null); + Debug.Assert(key != null); + if (RawDict.TryGetValue(key, out var result)) + { + if (result.Inserts > 0) + { + Debug.Assert(ValueComparer.Equals(value, result.Value), "Added key-value pair with mismatched value to existing data"); + } + // Now, make sure we override the value, since it may have been added in a remove, which MAY have passed the + // out-of-date value. + RawDict[key] = (value, result.Removes, result.Inserts + 1); + } + else + { + RawDict[key] = (value, 0, 1); + } + } + + /// + /// Completely clear the multidictionary. + /// + public void Clear() + { + RawDict.Clear(); + } + + /// + /// Remove a key from the dictionary. + /// + /// + public void Remove(TKey key, TValue value) + { + if (RawDict.TryGetValue(key, out var result)) + { + // DON'T assert that result.Value == value: if an update is happening, that may not be the case. + RawDict[key] = (result.Value, result.Removes + 1, result.Inserts); + } + else + { + RawDict[key] = (value, 1, 0); + } + } + + public override string ToString() + { + StringBuilder result = new(); + result.Append("SpacetimeDB.MultiDictionaryDelta { "); + foreach (var item in RawDict) + { + result.Append($"({item.Key}: {item.Value.Value}) x (+{item.Value.Inserts} -{item.Value.Removes}), "); + } + result.Append("}"); + return result.ToString(); + } + + public bool Equals(MultiDictionaryDelta other) + { + foreach (var item in RawDict) + { + var (key, my) = item; + if (other.RawDict.TryGetValue(key, out var their)) + { + if (!(ValueComparer.Equals(my.Value, their.Value) && my.Inserts == their.Inserts && my.Removes == their.Removes)) + { + return false; + } + } + } + + return true; + } + + public readonly IEnumerable> Entries + { + get + { + return RawDict; + } + } + } +} \ No newline at end of file diff --git a/sdks/csharp/src/MultiDictionary.cs.meta b/sdks/csharp/src/MultiDictionary.cs.meta new file mode 100644 index 00000000000..92f5b2c96d5 --- /dev/null +++ b/sdks/csharp/src/MultiDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0a96cc75d55b1f4283f07bb48f8ca4f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs index c9646b85605..ad06d90ad12 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs @@ -13,6 +13,8 @@ public partial record ClientMessage : SpacetimeDB.TaggedEnum<( Subscribe Subscribe, OneOffQuery OneOffQuery, SubscribeSingle SubscribeSingle, - Unsubscribe Unsubscribe + SubscribeMulti SubscribeMulti, + Unsubscribe Unsubscribe, + UnsubscribeMulti UnsubscribeMulti )>; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs index 5e0c12740f7..53e85fb8700 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs @@ -16,6 +16,8 @@ public partial record ServerMessage : SpacetimeDB.TaggedEnum<( OneOffQueryResponse OneOffQueryResponse, SubscribeApplied SubscribeApplied, UnsubscribeApplied UnsubscribeApplied, - SubscriptionError SubscriptionError + SubscriptionError SubscriptionError, + SubscribeMultiApplied SubscribeMultiApplied, + UnsubscribeMultiApplied UnsubscribeMultiApplied )>; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMulti.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMulti.g.cs new file mode 100644 index 00000000000..41bf0ec481f --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMulti.g.cs @@ -0,0 +1,40 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SubscribeMulti + { + [DataMember(Name = "query_strings")] + public System.Collections.Generic.List QueryStrings; + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "query_id")] + public QueryId QueryId; + + public SubscribeMulti( + System.Collections.Generic.List QueryStrings, + uint RequestId, + QueryId QueryId + ) + { + this.QueryStrings = QueryStrings; + this.RequestId = RequestId; + this.QueryId = QueryId; + } + + public SubscribeMulti() + { + this.QueryStrings = new(); + this.QueryId = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMulti.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMulti.g.cs.meta new file mode 100644 index 00000000000..68429491874 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMulti.g.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bca1b8b9e42c8c44da54059207cc331c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMultiApplied.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMultiApplied.g.cs new file mode 100644 index 00000000000..2f182a03df7 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMultiApplied.g.cs @@ -0,0 +1,44 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SubscribeMultiApplied + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "query_id")] + public QueryId QueryId; + [DataMember(Name = "update")] + public DatabaseUpdate Update; + + public SubscribeMultiApplied( + uint RequestId, + ulong TotalHostExecutionDurationMicros, + QueryId QueryId, + DatabaseUpdate Update + ) + { + this.RequestId = RequestId; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.QueryId = QueryId; + this.Update = Update; + } + + public SubscribeMultiApplied() + { + this.QueryId = new(); + this.Update = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMultiApplied.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMultiApplied.g.cs.meta new file mode 100644 index 00000000000..bbfb0fc6526 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeMultiApplied.g.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 617c823ceee44e449a26b57b0b085203 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMulti.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMulti.g.cs new file mode 100644 index 00000000000..e36d808b20c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMulti.g.cs @@ -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. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class UnsubscribeMulti + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "query_id")] + public QueryId QueryId; + + public UnsubscribeMulti( + uint RequestId, + QueryId QueryId + ) + { + this.RequestId = RequestId; + this.QueryId = QueryId; + } + + public UnsubscribeMulti() + { + this.QueryId = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMulti.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMulti.g.cs.meta new file mode 100644 index 00000000000..cf3f4444263 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMulti.g.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 170ba367e0a469043ac85da8f2d78edc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMultiApplied.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMultiApplied.g.cs new file mode 100644 index 00000000000..5cd5b992057 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMultiApplied.g.cs @@ -0,0 +1,44 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class UnsubscribeMultiApplied + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "query_id")] + public QueryId QueryId; + [DataMember(Name = "update")] + public DatabaseUpdate Update; + + public UnsubscribeMultiApplied( + uint RequestId, + ulong TotalHostExecutionDurationMicros, + QueryId QueryId, + DatabaseUpdate Update + ) + { + this.RequestId = RequestId; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.QueryId = QueryId; + this.Update = Update; + } + + public UnsubscribeMultiApplied() + { + this.QueryId = new(); + this.Update = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMultiApplied.g.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMultiApplied.g.cs.meta new file mode 100644 index 00000000000..ea39c611c0c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeMultiApplied.g.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef0d207c56b038d47a8ea8d22d94b022 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index a6f9e9871f7..217275a9554 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -10,7 +10,7 @@ using SpacetimeDB.Internal; using SpacetimeDB.ClientApi; using Thread = System.Threading.Thread; -using System.Diagnostics; + namespace SpacetimeDB { @@ -109,7 +109,7 @@ public interface IDbConnection internal void AddOnDisconnect(WebSocket.CloseEventHandler cb); internal void LegacySubscribe(ISubscriptionHandle handle, string[] querySqls); - internal void Subscribe(ISubscriptionHandle handle, string querySql); + internal void Subscribe(ISubscriptionHandle handle, string[] querySqls); internal void Unsubscribe(QueryId queryId); void FrameTick(); void Disconnect(); @@ -125,24 +125,6 @@ public abstract class DbConnectionBase : IDbConne { public static DbConnectionBuilder Builder() => new(); - readonly struct DbValue - { - public readonly IStructuralReadWrite value; - public readonly byte[] bytes; - - public DbValue(IStructuralReadWrite value, byte[] bytes) - { - this.value = value; - this.bytes = bytes; - } - } - - struct DbOp - { - public IRemoteTableHandle table; - public DbValue? delete; - public DbValue? insert; - } internal event Action? onConnect; @@ -218,25 +200,49 @@ struct UnprocessedMessage public DateTime timestamp; } + struct ProcessedDatabaseUpdate + { + // Map: table handles -> (primary key -> DbValue). + // If a particular table has no primary key, the "primary key" is just a byte[] + // storing the BSATN encoding of the row. + // See Decode(...). + public Dictionary> Updates; + + // Can't override the default constructor. Make sure you use this one! + public static ProcessedDatabaseUpdate New() + { + ProcessedDatabaseUpdate result; + result.Updates = new(); + return result; + } + + public MultiDictionaryDelta DeltaForTable(IRemoteTableHandle table) + { + if (!Updates.TryGetValue(table, out var delta)) + { + // Make sure we use GenericEqualityComparer here, since it handles byte[]s and arbitrary primary key types + // correctly. + delta = new MultiDictionaryDelta(GenericEqualityComparer.Instance, DbValueComparer.Instance); + Updates[table] = delta; + } + + return delta; + } + } + struct ProcessedMessage { public ServerMessage message; - public List dbOps; + public ProcessedDatabaseUpdate dbOps; public DateTime timestamp; public ReducerEvent? reducerEvent; } - struct PreProcessedMessage - { - public ProcessedMessage processed; - public Dictionary>? subscriptionInserts; - } - private readonly BlockingCollection _messageQueue = new(new ConcurrentQueue()); - private readonly BlockingCollection _preProcessedNetworkMessages = - new(new ConcurrentQueue()); + private readonly BlockingCollection _preProcessedNetworkMessages = + new(new ConcurrentQueue()); internal static bool IsTesting; internal bool HasPreProcessedMessage => _preProcessedNetworkMessages.Count > 0; @@ -244,10 +250,23 @@ struct PreProcessedMessage private readonly CancellationTokenSource _preProcessCancellationTokenSource = new(); private CancellationToken _preProcessCancellationToken => _preProcessCancellationTokenSource.Token; - static DbValue Decode(IRemoteTableHandle table, byte[] bin, out object? primaryKey) + /// + /// Decode a row for a table, producing a primary key. + /// If the table has a specific column marked `#[primary_key]`, use that. + /// If not, the BSATN for the entire row is used instead. + /// + /// + /// + /// + /// + static DbValue Decode(IRemoteTableHandle table, byte[] bin, out object primaryKey) { var obj = table.DecodeValue(bin); - primaryKey = table.GetPrimaryKey(obj); + // TODO(1.1): we should exhaustively check that GenericEqualityComparer works + // for all types that are allowed to be primary keys. + var primaryKey_ = table.GetPrimaryKey(obj); + primaryKey_ ??= bin; + primaryKey = primaryKey_; return new(obj, bin); } @@ -363,58 +382,37 @@ void PreProcessMessages() } } - (List, Dictionary>) PreProcessLegacySubscription(InitialSubscription initSub) + ProcessedDatabaseUpdate PreProcessLegacySubscription(InitialSubscription initSub) { - var dbOps = new List(); + var dbOps = ProcessedDatabaseUpdate.New(); // This is all of the inserts int cap = initSub.DatabaseUpdate.Tables.Sum(a => (int)a.NumRows); - // FIXME: shouldn't this be `new(initSub.DatabaseUpdate.Tables.Length)` ? - Dictionary> subscriptionInserts = new(capacity: cap); - - HashSet GetInsertHashSet(IRemoteTableHandle table, int tableSize) - { - if (!subscriptionInserts.TryGetValue(table, out var hashSet)) - { - hashSet = new HashSet(capacity: tableSize, comparer: ByteArrayComparer.Instance); - subscriptionInserts[table] = hashSet; - } - return hashSet; - } // First apply all of the state foreach (var (table, update) in GetTables(initSub.DatabaseUpdate)) { - var hashSet = GetInsertHashSet(table, (int)update.NumRows); - - PreProcessInsertOnlyTable(table, update, dbOps, hashSet); + PreProcessInsertOnlyTable(table, update, dbOps); } - return (dbOps, subscriptionInserts); + return dbOps; } /// /// TODO: the dictionary is here for backwards compatibility and can be removed /// once we get rid of legacy subscriptions. /// - (List, Dictionary>) PreProcessSubscribeApplied(SubscribeApplied subscribeApplied) + ProcessedDatabaseUpdate PreProcessSubscribeMultiApplied(SubscribeMultiApplied subscribeMultiApplied) { - var table = Db.GetTable(subscribeApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {subscribeApplied.Rows.TableName}"); - var dbOps = new List(); - HashSet inserts = new(comparer: ByteArrayComparer.Instance); - - PreProcessInsertOnlyTable(table, subscribeApplied.Rows.TableRows, dbOps, inserts); - - var result = new Dictionary> + var dbOps = ProcessedDatabaseUpdate.New(); + foreach (var (table, update) in GetTables(subscribeMultiApplied.Update)) { - [table] = inserts - }; - - return (dbOps, result); + PreProcessInsertOnlyTable(table, update, dbOps); + } + return dbOps; } - void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, List dbOps, HashSet inserts) + void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, ProcessedDatabaseUpdate dbOps) { - // In debug mode, make sure we use a byte array comparer in HashSet and not a reference-equal `byte[]` by accident. - Debug.Assert(inserts.Comparer is ByteArrayComparer); + var delta = dbOps.DeltaForTable(table); foreach (var cqu in update.Updates) { @@ -425,133 +423,74 @@ void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, Lis } foreach (var bin in BsatnRowListIter(qu.Inserts)) { - if (!inserts.Add(bin)) - { - // Ignore duplicate inserts in the same subscription update. - continue; - } - var obj = table.DecodeValue(bin); - var op = new DbOp - { - table = table, - insert = new(obj, bin), - }; - dbOps.Add(op); + var obj = Decode(table, bin, out var pk); + delta.Add(pk, obj); } } } - - /// - /// TODO: the dictionary is here for backwards compatibility and can be removed - /// once we get rid of legacy subscriptions. - /// - List PreProcessUnsubscribeApplied(UnsubscribeApplied unsubApplied) + void PreProcessDeleteOnlyTable(IRemoteTableHandle table, TableUpdate update, ProcessedDatabaseUpdate dbOps) { - var table = Db.GetTable(unsubApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {unsubApplied.Rows.TableName}"); - var dbOps = new List(); - - // First apply all of the state - foreach (var cqu in unsubApplied.Rows.TableRows.Updates) + var delta = dbOps.DeltaForTable(table); + foreach (var cqu in update.Updates) { var qu = DecompressDecodeQueryUpdate(cqu); if (qu.Inserts.RowsData.Count > 0) { - Log.Warn("Non-insert during an UnsubscribeApplied!"); + Log.Warn("Non-delete during a delete-only operation!"); } foreach (var bin in BsatnRowListIter(qu.Deletes)) { - var obj = table.DecodeValue(bin); - var op = new DbOp - { - table = table, - delete = new(obj, bin), - }; - dbOps.Add(op); + var obj = Decode(table, bin, out var pk); + delta.Remove(pk, obj); } } - - return dbOps; } + void PreProcessTable(IRemoteTableHandle table, TableUpdate update, ProcessedDatabaseUpdate dbOps) + { + var delta = dbOps.DeltaForTable(table); + foreach (var cqu in update.Updates) + { + var qu = DecompressDecodeQueryUpdate(cqu); + // Because we are accumulating into a MultiDictionaryDelta that will be applied all-at-once + // to the table, it doesn't matter that we call Add before Remove here. - List PreProcessDatabaseUpdate(DatabaseUpdate updates) - { - var dbOps = new List(); + foreach (var bin in BsatnRowListIter(qu.Inserts)) + { + var obj = Decode(table, bin, out var pk); + delta.Add(pk, obj); + } + foreach (var bin in BsatnRowListIter(qu.Deletes)) + { + var obj = Decode(table, bin, out var pk); + delta.Remove(pk, obj); + } + } - // All row updates that have a primary key, this contains inserts, deletes and updates. - // TODO: is there any guarantee that transaction update contains each table only once, aka updates are already grouped by table? - // If so, we could simplify this and other methods by moving the dictionary inside the main loop and using only the primary key as key. - var primaryKeyChanges = new Dictionary<(IRemoteTableHandle table, object primaryKeyValue), DbOp>(); + } - // First apply all of the state - foreach (var (table, update) in GetTables(updates)) + ProcessedDatabaseUpdate PreProcessUnsubscribeMultiApplied(UnsubscribeMultiApplied unsubMultiApplied) + { + var dbOps = ProcessedDatabaseUpdate.New(); + + foreach (var (table, update) in GetTables(unsubMultiApplied.Update)) { - foreach (var cqu in update.Updates) - { - var qu = DecompressDecodeQueryUpdate(cqu); - foreach (var row in BsatnRowListIter(qu.Inserts)) - { - var op = new DbOp { table = table, insert = Decode(table, row, out var pk) }; - if (pk != null) - { - // Compound key that we use for lookup. - // Consists of the table handle (for faster comparison that string names) + actual primary key of the row. - var key = (table, pk); + PreProcessDeleteOnlyTable(table, update, dbOps); + } - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) - { - if (oldOp.insert is not null) - { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={update.TableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; - } - - op.delete = oldOp.delete; - } - primaryKeyChanges[key] = op; - } - else - { - dbOps.Add(op); - } - } + return dbOps; + } - foreach (var row in BsatnRowListIter(qu.Deletes)) - { - var op = new DbOp { table = table, delete = Decode(table, row, out var pk) }; - if (pk != null) - { - // Compound key that we use for lookup. - // Consists of the table handle (for faster comparison that string names) + actual primary key of the row. - var key = (table, pk); + ProcessedDatabaseUpdate PreProcessDatabaseUpdate(DatabaseUpdate updates) + { + var dbOps = ProcessedDatabaseUpdate.New(); - if (primaryKeyChanges.TryGetValue(key, out var oldOp)) - { - if (oldOp.delete is not null) - { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={update.TableName}"); - // TODO(jdetter): Is this a correctable error? This would be a major error on the - // SpacetimeDB side. - continue; - } - - op.insert = oldOp.insert; - } - primaryKeyChanges[key] = op; - } - else - { - dbOps.Add(op); - } - } - } + foreach (var (table, update) in GetTables(updates)) + { + PreProcessTable(table, update, dbOps); } - // Combine primary key updates and non-primary key updates - dbOps.AddRange(primaryKeyChanges.Values); return dbOps; } @@ -569,29 +508,32 @@ void PreProcessOneOffQuery(OneOffQueryResponse resp) resultSource.SetResult(resp); } - PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) + ProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) { - var dbOps = new List(); + var dbOps = ProcessedDatabaseUpdate.New(); var message = DecompressDecodeMessage(unprocessed.bytes); ReducerEvent? reducerEvent = default; - // This is all of the inserts, used for updating the stale but un-cleared client cache. - Dictionary>? subscriptionInserts = null; - switch (message) { case ServerMessage.InitialSubscription(var initSub): - (dbOps, subscriptionInserts) = PreProcessLegacySubscription(initSub); + dbOps = PreProcessLegacySubscription(initSub); break; case ServerMessage.SubscribeApplied(var subscribeApplied): - (dbOps, subscriptionInserts) = PreProcessSubscribeApplied(subscribeApplied); + break; + case ServerMessage.SubscribeMultiApplied(var subscribeMultiApplied): + dbOps = PreProcessSubscribeMultiApplied(subscribeMultiApplied); break; case ServerMessage.SubscriptionError(var subscriptionError): + // do nothing; main thread will warn. break; case ServerMessage.UnsubscribeApplied(var unsubscribeApplied): - dbOps = PreProcessUnsubscribeApplied(unsubscribeApplied); + // do nothing; main thread will warn. + break; + case ServerMessage.UnsubscribeMultiApplied(var unsubscribeMultiApplied): + dbOps = PreProcessUnsubscribeMultiApplied(unsubscribeMultiApplied); break; case ServerMessage.TransactionUpdate(var transactionUpdate): // Convert the generic event arguments in to a domain specific event object @@ -636,40 +578,10 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) throw new InvalidOperationException(); } - return new PreProcessedMessage - { - processed = new ProcessedMessage { message = message, dbOps = dbOps, timestamp = unprocessed.timestamp, reducerEvent = reducerEvent }, - subscriptionInserts = subscriptionInserts, - }; + return new ProcessedMessage { message = message, dbOps = dbOps, timestamp = unprocessed.timestamp, reducerEvent = reducerEvent }; } } - ProcessedMessage CalculateStateDiff(PreProcessedMessage preProcessedMessage) - { - var processed = preProcessedMessage.processed; - - // Perform the state diff, this has to be done on the main thread because we have to touch - // the client cache. - if (preProcessedMessage.subscriptionInserts is { } subscriptionInserts) - { - foreach (var (table, hashSet) in subscriptionInserts) - { - foreach (var (rowBytes, oldValue) in table.IterEntries().Where(kv => !hashSet.Contains(kv.Key))) - { - processed.dbOps.Add(new DbOp - { - table = table, - // This is a row that we had before, but we do not have it now. - // This must have been a delete. - delete = new(oldValue, rowBytes), - }); - } - } - } - - return processed; - } - public void Disconnect() { isClosing = true; @@ -720,81 +632,30 @@ void IDbConnection.Connect(string? token, string uri, string addressOrName, Comp } } - private void OnMessageProcessCompleteUpdate(IEventContext eventContext, List dbOps) + + private void OnMessageProcessCompleteUpdate(IEventContext eventContext, ProcessedDatabaseUpdate dbOps) { // First trigger OnBeforeDelete - foreach (var update in dbOps) + foreach (var (table, update) in dbOps.Updates) { - if (update is { delete: { value: var oldValue }, insert: null }) - { - try - { - update.table.InvokeBeforeDelete(eventContext, oldValue); - } - catch (Exception e) - { - Log.Exception(e); - } - } + table.PreApply(eventContext, update); } - // Apply all of the state - for (var i = 0; i < dbOps.Count; i++) + foreach (var (table, update) in dbOps.Updates) { - // TODO: Reimplement updates when we add support for primary keys - var update = dbOps[i]; - - if (update.delete is { } delete) - { - if (!update.table.DeleteEntry(delete.bytes)) - { - update.delete = null; - dbOps[i] = update; - } - } - - if (update.insert is { } insert) - { - if (!update.table.InsertEntry(insert.bytes, insert.value)) - { - update.insert = null; - dbOps[i] = update; - } - } + table.Apply(eventContext, update); } - // Send out events - foreach (var dbOp in dbOps) + foreach (var (table, _) in dbOps.Updates) { - try - { - switch (dbOp) - { - case { insert: { value: var newValue }, delete: { value: var oldValue } }: - dbOp.table.InvokeUpdate(eventContext, oldValue, newValue); - break; - - case { insert: { value: var newValue } }: - dbOp.table.InvokeInsert(eventContext, newValue); - break; - - case { delete: { value: var oldValue } }: - dbOp.table.InvokeDelete(eventContext, oldValue); - break; - } - } - catch (Exception e) - { - Log.Exception(e); - } + table.PostApply(eventContext); } } protected abstract bool Dispatch(IReducerEventContext context, Reducer reducer); - private void OnMessageProcessComplete(PreProcessedMessage preProcessed) + private void OnMessageProcessComplete(ProcessedMessage processed) { - var processed = CalculateStateDiff(preProcessed); var message = processed.message; var dbOps = processed.dbOps; var timestamp = processed.timestamp; @@ -824,17 +685,21 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } case ServerMessage.SubscribeApplied(var subscribeApplied): + Log.Warn($"Unexpected SubscribeApplied (we only expect to get SubscribeMultiApplied): {subscribeApplied}"); + break; + + case ServerMessage.SubscribeMultiApplied(var subscribeMultiApplied): { stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.SubscribeApplied)}"); - stats.SubscriptionRequestTracker.FinishTrackingRequest(subscribeApplied.RequestId); + stats.SubscriptionRequestTracker.FinishTrackingRequest(subscribeMultiApplied.RequestId); var eventContext = MakeSubscriptionEventContext(); var legacyEventContext = ToEventContext(new Event.SubscribeApplied()); OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); - if (subscriptions.TryGetValue(subscribeApplied.QueryId.Id, out var subscription)) + if (subscriptions.TryGetValue(subscribeMultiApplied.QueryId.Id, out var subscription)) { try { - subscription.OnApplied(eventContext, new SubscriptionAppliedType.Active(subscribeApplied.QueryId)); + subscription.OnApplied(eventContext, new SubscriptionAppliedType.Active(subscribeMultiApplied.QueryId)); } catch (Exception e) { @@ -882,13 +747,17 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } case ServerMessage.UnsubscribeApplied(var unsubscribeApplied): + Log.Warn($"Unexpected UnsubscribeApplied (we only expect to get UnsubscribeMultiApplied): {unsubscribeApplied}"); + break; + + case ServerMessage.UnsubscribeMultiApplied(var unsubscribeMultiApplied): { stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.UnsubscribeApplied)}"); - stats.SubscriptionRequestTracker.FinishTrackingRequest(unsubscribeApplied.RequestId); + stats.SubscriptionRequestTracker.FinishTrackingRequest(unsubscribeMultiApplied.RequestId); var eventContext = MakeSubscriptionEventContext(); var legacyEventContext = ToEventContext(new Event.UnsubscribeApplied()); OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); - if (subscriptions.TryGetValue(unsubscribeApplied.QueryId.Id, out var subscription)) + if (subscriptions.TryGetValue(unsubscribeMultiApplied.QueryId.Id, out var subscription)) { try { @@ -929,8 +798,6 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } } - - if (processed.reducerEvent is { } reducerEvent) { var legacyEventContext = ToEventContext(new Event.Reducer(reducerEvent)); @@ -1007,7 +874,7 @@ void IDbConnection.LegacySubscribe(ISubscriptionHandle handle, string[] querySql )); } - void IDbConnection.Subscribe(ISubscriptionHandle handle, string querySql) + void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) { if (!webSocket.IsConnected) { @@ -1020,11 +887,11 @@ void IDbConnection.Subscribe(ISubscriptionHandle handle, string querySql) // casting request IDs to query IDs anywhere in the new code path. var queryId = queryIdAllocator.Next(); subscriptions[queryId] = handle; - webSocket.Send(new ClientMessage.SubscribeSingle( - new SubscribeSingle + webSocket.Send(new ClientMessage.SubscribeMulti( + new SubscribeMulti { RequestId = id, - Query = querySql, + QueryStrings = querySqls.ToList(), QueryId = new QueryId(queryId), } )); @@ -1110,7 +977,7 @@ void IDbConnection.Unsubscribe(QueryId queryId) var requestId = stats.SubscriptionRequestTracker.StartTrackingRequest(); - webSocket.Send(new ClientMessage.Unsubscribe(new() + webSocket.Send(new ClientMessage.UnsubscribeMulti(new() { RequestId = requestId, QueryId = queryId @@ -1139,4 +1006,32 @@ public uint Next() return lastAllocated; } } + internal readonly struct DbValue + { + public readonly IStructuralReadWrite value; + public readonly byte[] bytes; + + public DbValue(IStructuralReadWrite value, byte[] bytes) + { + this.value = value; + this.bytes = bytes; + } + + // TODO: having a nice ToString here would give better way better errors when applying table deltas, + // but it's tricky to do that generically. + } + + /// + /// DbValue comparer that uses BSATN-encoded records to compare DbValues for equality. + /// + internal readonly struct DbValueComparer : IEqualityComparer + { + public static DbValueComparer Instance = new(); + + public bool Equals(DbValue x, DbValue y) => + ByteArrayComparer.Instance.Equals(x.bytes, y.bytes); + + public int GetHashCode(DbValue obj) => + ByteArrayComparer.Instance.GetHashCode(obj.bytes); + } } diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index 35d76bb496d..9f10d632008 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; - using SpacetimeDB.BSATN; namespace SpacetimeDB @@ -23,17 +23,31 @@ public interface IRemoteTableHandle internal string RemoteTableName { get; } internal Type ClientTableType { get; } - internal IEnumerable> IterEntries(); - internal bool InsertEntry(byte[] rowBytes, IStructuralReadWrite value); - internal bool DeleteEntry(byte[] rowBytes); internal IStructuralReadWrite DecodeValue(byte[] bytes); - internal void InvokeInsert(IEventContext context, IStructuralReadWrite row); - internal void InvokeDelete(IEventContext context, IStructuralReadWrite row); - internal void InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row); - internal void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructuralReadWrite newRow); + /// + /// Start applying a delta to the table. + /// This is called for all tables before any updates are actually applied, allowing OnBeforeDelete to be invoked correctly. + /// + /// + internal void PreApply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta); + + /// + /// Apply a delta to the table. + /// Should not invoke any user callbacks, since not all tables have been updated yet. + /// Should fix up indices, to be ready for PostApply. + /// + /// + internal void Apply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta); + + /// + /// Finish applying a delta to a table. + /// This is when row callbacks (besides OnBeforeDelete) actually happen. + /// + internal void PostApply(IEventContext context); } + public abstract class RemoteTableHandle : RemoteBase, IRemoteTableHandle where EventContext : class, IEventContext where Row : class, IStructuralReadWrite, new() @@ -105,6 +119,7 @@ public RemoteTableHandle(IDbConnection conn) : base(conn) { } // TODO: figure out if they can be merged into regular OnInsert / OnDelete. // I didn't do that because that delays the index updates until after the row is processed. // In theory, that shouldn't be the issue, but I didn't want to break it right before leaving :) + // - Ingvar private event Action? OnInternalInsert; private event Action? OnInternalDelete; @@ -114,76 +129,208 @@ public RemoteTableHandle(IDbConnection conn) : base(conn) { } // These are provided by RemoteTableHandle. Type IRemoteTableHandle.ClientTableType => typeof(Row); - private readonly Dictionary Entries = new(Internal.ByteArrayComparer.Instance); + // THE DATA IN THE TABLE. + // The keys of this map are: + // - Primary keys, if we have them. + // - Byte arrays, if we don't. + // But really, the keys are whatever SpacetimeDBClient chooses to give us. + // + // We store the BSATN encodings of objects next to their runtime representation. + // This is memory-inefficient, but allows us to quickly compare objects when seeing if an update is a "real" + // update or just a multiplicity change. + private readonly MultiDictionary Entries = new(GenericEqualityComparer.Instance, DbValueComparer.Instance); - IEnumerable> IRemoteTableHandle.IterEntries() => - Entries.Select(kv => new KeyValuePair(kv.Key, kv.Value)); + // The function to use for decoding a type value. + IStructuralReadWrite IRemoteTableHandle.DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); - /// - /// Inserts the value into the table. There can be no existing value with the provided BSATN bytes. - /// - /// The BSATN encoded bytes of the row to retrieve. - /// The parsed row encoded by the rowBytes. - /// True if the row was inserted, false if the row wasn't inserted because it was a duplicate. - bool IRemoteTableHandle.InsertEntry(byte[] rowBytes, IStructuralReadWrite value) + public delegate void RowEventHandler(EventContext context, Row row); + public event RowEventHandler? OnInsert; + public event RowEventHandler? OnDelete; + public event RowEventHandler? OnBeforeDelete; + + public delegate void UpdateEventHandler(EventContext context, Row oldRow, Row newRow); + public event UpdateEventHandler? OnUpdate; + + public int Count => (int)Entries.CountDistinct; + + public IEnumerable Iter() => Entries.Entries.Select(entry => (Row)entry.Value.value); + + public Task RemoteQuery(string query) => + conn.RemoteQuery($"SELECT {RemoteTableName}.* FROM {RemoteTableName} {query}"); + + void InvokeInsert(IEventContext context, IStructuralReadWrite row) { - var row = (Row)value; - if (Entries.TryAdd(rowBytes, row)) + try { - OnInternalInsert?.Invoke(row); - return true; + OnInsert?.Invoke((EventContext)context, (Row)row); } - else + catch (Exception e) { - return false; + Log.Exception(e); } } - /// - /// Deletes a value from the table. - /// - /// The BSATN encoded bytes of the row to remove. - /// True if and only if the value was previously resident and has been deleted. - bool IRemoteTableHandle.DeleteEntry(byte[] rowBytes) + void InvokeDelete(IEventContext context, IStructuralReadWrite row) { - if (Entries.Remove(rowBytes, out var row)) + try { - OnInternalDelete?.Invoke(row); - return true; + OnDelete?.Invoke((EventContext)context, (Row)row); } + catch (Exception e) + { + Log.Exception(e); + } + } - Log.Warn("Deleting value that we don't have (no cached value available)"); - return false; + void InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row) + { + try + { + OnBeforeDelete?.Invoke((EventContext)context, (Row)row); + } + catch (Exception e) + { + Log.Exception(e); + } } - // The function to use for decoding a type value. - IStructuralReadWrite IRemoteTableHandle.DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); + void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructuralReadWrite newRow) + { + try + { + OnUpdate?.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); + } + catch (Exception e) + { + Log.Exception(e); + } + } - public delegate void RowEventHandler(EventContext context, Row row); - public event RowEventHandler? OnInsert; - public event RowEventHandler? OnDelete; - public event RowEventHandler? OnBeforeDelete; + List> wasInserted = new(); + List<(object key, DbValue oldValue, DbValue newValue)> wasUpdated = new(); + List> wasRemoved = new(); - public delegate void UpdateEventHandler(EventContext context, Row oldRow, Row newRow); - public event UpdateEventHandler? OnUpdate; + void IRemoteTableHandle.PreApply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta) + { + Debug.Assert(wasInserted.Count == 0 && wasUpdated.Count == 0 && wasRemoved.Count == 0, "Call Apply and PostApply before calling PreApply again"); - public int Count => Entries.Count; + foreach (var (_, value) in Entries.WillRemove(multiDictionaryDelta)) + { + InvokeBeforeDelete(context, value.value); + } + } - public IEnumerable Iter() => Entries.Values; + void IRemoteTableHandle.Apply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta) + { + try + { + Entries.Apply(multiDictionaryDelta, wasInserted, wasUpdated, wasRemoved); + } + catch (Exception e) + { + var deltaString = multiDictionaryDelta.ToString(); + deltaString = deltaString[..Math.Min(deltaString.Length, 10_000)]; + var entriesString = Entries.ToString(); + entriesString = entriesString[..Math.Min(entriesString.Length, 10_000)]; + throw new Exception($"While table `{RemoteTableName}` was applying:\n{deltaString} \nto:\n{entriesString}", e); + } - public Task RemoteQuery(string query) => - conn.RemoteQuery($"SELECT {RemoteTableName}.* FROM {RemoteTableName} {query}"); + // Update indices. + // This is a local operation -- it only looks at our indices and doesn't invoke user code. + // So we don't need to wait for other tables to be updated to do it. + // (And we need to do it before any PostApply is called.) + foreach (var (_, value) in wasInserted) + { + if (value.value is Row newRow) + { + OnInternalInsert?.Invoke(newRow); + } + else + { + throw new Exception($"Invalid row type for table {RemoteTableName}: {value.value.GetType().Name}"); + } + } + foreach (var (_, oldValue, newValue) in wasUpdated) + { + if (oldValue.value is Row oldRow) + { + OnInternalDelete?.Invoke((Row)oldValue.value); + } + else + { + throw new Exception($"Invalid row type for table {RemoteTableName}: {oldValue.value.GetType().Name}"); + } - void IRemoteTableHandle.InvokeInsert(IEventContext context, IStructuralReadWrite row) => - OnInsert?.Invoke((EventContext)context, (Row)row); - void IRemoteTableHandle.InvokeDelete(IEventContext context, IStructuralReadWrite row) => - OnDelete?.Invoke((EventContext)context, (Row)row); + if (newValue.value is Row newRow) + { + OnInternalInsert?.Invoke(newRow); + } + else + { + throw new Exception($"Invalid row type for table {RemoteTableName}: {newValue.value.GetType().Name}"); + } + } - void IRemoteTableHandle.InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row) => - OnBeforeDelete?.Invoke((EventContext)context, (Row)row); + foreach (var (_, value) in wasRemoved) + { + if (value.value is Row oldRow) + { + OnInternalDelete?.Invoke(oldRow); + } + } + } + + void IRemoteTableHandle.PostApply(IEventContext context) + { + foreach (var (_, value) in wasInserted) + { + InvokeInsert(context, value.value); + } + foreach (var (_, oldValue, newValue) in wasUpdated) + { + InvokeUpdate(context, oldValue.value, newValue.value); + } + foreach (var (_, value) in wasRemoved) + { + InvokeDelete(context, value.value); + } + wasInserted.Clear(); + wasUpdated.Clear(); + wasRemoved.Clear(); + + } + } + + /// + /// EqualityComparer used to compare primary keys. + /// + /// If the primary keys are byte arrays (i.e. if the table has no primary key), uses Internal.ByteArrayComparer. + /// Otherwise, falls back to .Equals(). + /// + /// TODO: we should test that this works for all of our supported primary key types. + /// + internal readonly struct GenericEqualityComparer : IEqualityComparer + { + public static GenericEqualityComparer Instance = new(); + + public new bool Equals(object x, object y) + { + if (x is byte[] x_ && y is byte[] y_) + { + return Internal.ByteArrayComparer.Instance.Equals(x_, y_); + } + return x.Equals(y); // MAKE SURE to use .Equals and not ==... that was a bug. + } + + public int GetHashCode(object obj) + { + if (obj is byte[] obj_) + { + return Internal.ByteArrayComparer.Instance.GetHashCode(obj_); + } + return obj.GetHashCode(); + } - void IRemoteTableHandle.InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructuralReadWrite newRow) => - OnUpdate?.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); } } diff --git a/sdks/csharp/tests~/MultiDictionaryTests.cs b/sdks/csharp/tests~/MultiDictionaryTests.cs new file mode 100644 index 00000000000..0012c9c7445 --- /dev/null +++ b/sdks/csharp/tests~/MultiDictionaryTests.cs @@ -0,0 +1,244 @@ +using System.Diagnostics; +using CsCheck; +using SpacetimeDB; +using Xunit; + +public class MultiDictionaryTests +{ + /// + /// Generate a list of KeyValuePairs. + /// If any two items of the list have duplicate Keys, they are guaranteed to have duplicate Values. + /// + /// + /// + /// + /// + /// + /// + Gen>> ListWithNormalizedDuplicates(Gen g1, Gen g2, IEqualityComparer equality, int ListMinLength = 0, int ListMaxLength = 32) + where TKey : notnull + { + return Gen.Select(g1, g2, (b1, b2) => new KeyValuePair(b1, b2)).List[ListMinLength, ListMaxLength].Select(list => + { + Dictionary seenKeys = new(equality); + for (var i = 0; i < list.Count; i++) + { + var (b1, b2) = list[i]; + if (seenKeys.ContainsKey(b1)) + { + list[i] = new(b1, seenKeys[b1]); + } + else + { + seenKeys[b1] = b2; + } + } + return list; + }); + } + + [Fact] + public void Equality() + { + // No matter the order we add elements to the multidictionary, the result should be the same. + ListWithNormalizedDuplicates(Gen.Byte[1, 10], Gen.Byte[1, 10], EqualityComparer.Default).Sample(list => + { + var m1 = MultiDictionary.FromEnumerable(list, EqualityComparer.Default, EqualityComparer.Default); + Gen.Shuffle(list); + var m2 = MultiDictionary.FromEnumerable(list, EqualityComparer.Default, EqualityComparer.Default); + + Assert.Equal(m1, m2); + }); + + ListWithNormalizedDuplicates(Gen.Byte[1, 10].Array[1, 10], Gen.Byte[1, 10], SpacetimeDB.Internal.ByteArrayComparer.Instance).Sample(list => + { + var m1 = MultiDictionary.FromEnumerable(list, SpacetimeDB.Internal.ByteArrayComparer.Instance, EqualityComparer.Default); + Gen.Shuffle(list); + var m2 = MultiDictionary.FromEnumerable(list, SpacetimeDB.Internal.ByteArrayComparer.Instance, EqualityComparer.Default); + + Assert.Equal(m1, m2); + }); + + } + + /// + /// Generate a list of KeyValuePairs, and a list of bools that say whether or not to remove that key-value pair. + /// + /// + /// + /// + /// + /// + /// + /// + Gen<(List>, List)> ListWithRemovals(Gen g1, Gen g2, IEqualityComparer equality, + int maxLength = 32) + where TKey : notnull + => Gen.SelectMany( + Gen.Int[0, maxLength], (listLength) => Gen.Select( + // the data itself + ListWithNormalizedDuplicates(g1, g2, equality, listLength, listLength), + // whether this element should be added or removed + Gen.Bool.List[listLength] + )); + + [Fact] + public void Removals() + { + ListWithRemovals(Gen.Byte[1, 10], Gen.Byte[1, 10], EqualityComparer.Default).Sample((list, removals) => + { + // Build up two MultiDictionaries: + // - for m1, add everything, then remove stuff. + // - for m2, only add the non-removed stuff. + // The result should be the same. + var m1 = MultiDictionary.FromEnumerable(list, EqualityComparer.Default, EqualityComparer.Default); + var m2 = new MultiDictionary(EqualityComparer.Default, EqualityComparer.Default); + foreach (var (kvp, remove) in list.Zip(removals)) + { + if (remove) + { + m1.Remove(kvp.Key, out var _); + } + else + { + m2.Add(kvp.Key, kvp.Value); + } + } + + Assert.Equal(m1, m2); + }); + } + + [Fact] + public void ShuffleDelta() + { + ListWithRemovals(Gen.Byte[1, 10], Gen.Byte[1, 10], EqualityComparer.Default).Sample((list, removals) => + { + // Check that no matter the order you apply Adds and Removes to a MultiDictionaryDelta, the result is the same. + var m1 = new MultiDictionaryDelta(EqualityComparer.Default, EqualityComparer.Default); + var m2 = new MultiDictionaryDelta(EqualityComparer.Default, EqualityComparer.Default); + var listRemovals = list.Zip(removals).ToList(); + foreach (var (kvp, remove) in listRemovals) + { + if (remove) + { + m1.Remove(kvp.Key, kvp.Value); + } + else + { + m1.Add(kvp.Key, kvp.Value); + } + } + Gen.Shuffle(listRemovals); + foreach (var (kvp, remove) in listRemovals) + { + if (remove) + { + m2.Remove(kvp.Key, kvp.Value); + } + else + { + m2.Add(kvp.Key, kvp.Value); + } + } + + Assert.Equal(m1, m2); + }); + } + + [Fact] + public void ChunkedRemovals() + { + var maxLength = 32; + Gen.Select(ListWithRemovals(Gen.Byte[1, 10], Gen.Byte[1, 10], EqualityComparer.Default, maxLength), Gen.Int[0, 32].List[0, 5]).Sample((listRemovals, cuts) => + { + // Test that building up a MultiDictionary an operation-at-a-time is the same as randomly grouping the operations and applying them in chunks using MultiDictionaryDeltas. + // Note: When looking at test failures for this test, keep in mind we do some post-processing of the sample input data. + // So the listed `removals` and `cuts` may be changed slightly during the test. + var (list, removals) = listRemovals; + cuts.Add(0); + cuts.Add(maxLength); + cuts = cuts.Select(cut => int.Min(cut, list.Count)).ToList(); + cuts.Sort(); + + var viaAddRemove = new MultiDictionary(EqualityComparer.Default, EqualityComparer.Default); + var viaChunkDeltas = new MultiDictionary(EqualityComparer.Default, EqualityComparer.Default); + + if (list.Count == 0) + { + return; + } + + foreach (var (start, end) in cuts.Zip(cuts.Skip(1))) + { + var delta = new MultiDictionaryDelta(EqualityComparer.Default, EqualityComparer.Default); + + var (start_, end_) = (int.Min(start, list.Count), int.Min(end, list.Count)); + + foreach (var (item, remove) in list[start..end].Zip(removals[start..end])) + { + // it's an error to remove-too-many-times with the Delta api. + // so, don't remove anything we don't have. + var remove_ = remove && viaAddRemove.Contains(item); + if (remove_) + { + viaAddRemove.Remove(item.Key, out var _); + delta.Remove(item.Key, item.Value); + } + else + { + viaAddRemove.Add(item.Key, item.Value); + delta.Add(item.Key, item.Value); + } + } + foreach (var (key, value) in viaChunkDeltas.WillRemove(delta)) + { + Assert.True(viaChunkDeltas.Contains(new(key, value))); + } + var wasInserted = new List>(); + var wasMaybeUpdated = new List<(byte key, byte oldValue, byte newValue)>(); + var wasRemoved = new List>(); + + viaChunkDeltas.Apply(delta, wasInserted, wasMaybeUpdated, wasRemoved); + foreach (var (key, value) in wasInserted) + { + Assert.True(viaChunkDeltas.Contains(new(key, value))); + } + foreach (var (key, oldValue, newValue) in wasMaybeUpdated) + { + Assert.True(viaChunkDeltas.Contains(new(key, newValue)) && oldValue == newValue); + } + foreach (var (key, value) in wasRemoved) + { + Assert.False(viaChunkDeltas.Contains(new(key, value))); + } + Assert.Equal(viaAddRemove, viaChunkDeltas); + } + }, iter: 10_000); + } + + [Fact] + public void IdentitiesWorkAsPrimaryKeys() + { + // GenericEqualityComparer used to have a bug, this is a regression test for that. + var identity = Identity.From(Convert.FromBase64String("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=")); + var hashSet = new HashSet(GenericEqualityComparer.Instance) + { + identity + }; + Debug.Assert(hashSet.Contains(identity)); + + var dict = new MultiDictionary(GenericEqualityComparer.Instance, EqualityComparer.Default); + + dict.Add(identity, 3); + dict.Add(identity, 3); + + var delta = new MultiDictionaryDelta(GenericEqualityComparer.Instance, EqualityComparer.Default); + delta.Remove(identity, 3); + delta.Remove(identity, 3); + var wasInserted = new List>(); + var wasMaybeUpdated = new List<(object key, byte oldValue, byte newValue)>(); + var wasRemoved = new List>(); + dict.Apply(delta, wasInserted, wasMaybeUpdated, wasRemoved); + } +} \ No newline at end of file diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 66a6b39537b..3c0606f9a43 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -12,7 +12,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, user: { identity: Identity_1, @@ -26,7 +29,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, user: { identity: Identity_2, @@ -43,7 +49,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.IdentityConnected @@ -52,7 +58,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, user: { identity: Identity_3, @@ -69,7 +78,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -79,7 +88,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, oldUser: { identity: Identity_1, @@ -98,7 +110,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -115,7 +127,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnInsertMessage: { eventContext: { @@ -127,7 +142,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -137,7 +152,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_3, @@ -152,7 +170,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -169,7 +187,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnUpdateUser: { eventContext: { @@ -181,7 +202,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -191,7 +212,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, oldUser: { identity: Identity_3, @@ -210,7 +234,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -227,7 +251,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnInsertMessage: { eventContext: { @@ -239,7 +266,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -249,7 +276,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_1, @@ -264,7 +294,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -281,7 +311,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnInsertMessage: { eventContext: { @@ -293,7 +326,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -303,7 +336,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_3, @@ -318,7 +354,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -335,7 +371,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnUpdateUser: { eventContext: { @@ -347,7 +386,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.IdentityDisconnected @@ -356,7 +395,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, oldUser: { identity: Identity_3, @@ -379,7 +421,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -389,7 +431,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_1, @@ -404,7 +449,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -421,7 +466,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 } }, FinalSnapshot: { diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index 353c6ad230c..2f054c9e1c7 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -12,7 +12,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, user: { identity: Identity_1, @@ -26,7 +29,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, user: { identity: Identity_2, @@ -43,7 +49,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.IdentityConnected @@ -52,7 +58,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, user: { identity: Identity_3, @@ -69,7 +78,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -79,7 +88,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, oldUser: { identity: Identity_1, @@ -98,7 +110,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -115,7 +127,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnInsertMessage: { eventContext: { @@ -127,7 +142,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -137,7 +152,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_3, @@ -152,7 +170,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -169,7 +187,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnUpdateUser: { eventContext: { @@ -181,7 +202,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -191,7 +212,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, oldUser: { identity: Identity_3, @@ -210,7 +234,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SetName, @@ -227,7 +251,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnInsertMessage: { eventContext: { @@ -239,7 +266,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -249,7 +276,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_1, @@ -264,7 +294,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -281,7 +311,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnInsertMessage: { eventContext: { @@ -293,7 +326,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -303,7 +336,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_3, @@ -318,7 +354,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -335,7 +371,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnUpdateUser: { eventContext: { @@ -347,7 +386,7 @@ $type: Status.Committed }, CallerIdentity: Identity_3, - CallerConnectionId: Guid_1, + CallerConnectionId: Guid_2, EnergyConsumed: {}, Reducer: { $type: Reducer.IdentityDisconnected @@ -356,7 +395,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, oldUser: { identity: Identity_3, @@ -379,7 +421,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -389,7 +431,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_1, @@ -404,7 +449,7 @@ $type: Status.Committed }, CallerIdentity: Identity_1, - CallerConnectionId: Guid_2, + CallerConnectionId: Guid_3, EnergyConsumed: {}, Reducer: { $type: Reducer.SendMessage, @@ -421,7 +466,10 @@ } }, Reducers: {}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, OnDeleteMessage: { eventContext: { @@ -430,7 +478,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_3, @@ -445,7 +496,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_1, @@ -460,7 +514,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_3, @@ -475,7 +532,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_1, @@ -491,7 +551,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_3, @@ -506,7 +569,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_1, @@ -521,7 +587,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_3, @@ -536,7 +605,10 @@ }, Db: {Scrubbed}, Reducers: {Scrubbed}, - SetReducerFlags: {} + SetReducerFlags: {}, + IsActive: false, + Identity: Identity_1, + ConnectionId: Guid_1 }, message: { sender: Identity_1, @@ -591,10 +663,7 @@ requestsAwaitingResponse: 6 }, OneOffRequestTracker: {}, - SubscriptionRequestTracker: { - sampleCount: 1, - requestsAwaitingResponse: 2 - }, + SubscriptionRequestTracker: {}, AllReducersTracker: { sampleCount: 9 }, diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 11c2fa71b43..eab22149c6f 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -118,7 +118,7 @@ List updates } }); - private static ServerMessage.SubscribeApplied SampleSubscribeApplied( + private static ServerMessage.SubscribeMultiApplied SampleSubscribeApplied( uint requestId, uint queryId, ulong hostExecutionDuration, @@ -126,19 +126,12 @@ TableUpdate tableUpdate ) => new(new() { RequestId = requestId, - TotalHostExecutionDurationMicros = hostExecutionDuration, QueryId = new(queryId), - Rows = new() - { - // This message contains redundant data, shrug. - // Copy out the redundant fields. - TableId = tableUpdate.TableId, - TableName = tableUpdate.TableName, - TableRows = tableUpdate - } + TotalHostExecutionDurationMicros = hostExecutionDuration, + Update = new(new List { tableUpdate }) }); - private static ServerMessage.UnsubscribeApplied SampleUnsubscribeApplied( + private static ServerMessage.UnsubscribeMultiApplied SampleUnsubscribeApplied( uint requestId, uint queryId, ulong hostExecutionDuration, @@ -148,14 +141,7 @@ TableUpdate tableUpdate RequestId = requestId, TotalHostExecutionDurationMicros = hostExecutionDuration, QueryId = new(queryId), - Rows = new() - { - // This message contains redundant data, shrug. - // Copy out the redundant fields. - TableId = tableUpdate.TableId, - TableName = tableUpdate.TableName, - TableRows = tableUpdate - } + Update = new(new List { tableUpdate }) }); private static ServerMessage.SubscriptionError SampleSubscriptionError( diff --git a/sdks/csharp/tests~/tests.csproj b/sdks/csharp/tests~/tests.csproj index 804fa736c4d..87b71a1fa10 100644 --- a/sdks/csharp/tests~/tests.csproj +++ b/sdks/csharp/tests~/tests.csproj @@ -17,6 +17,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index 3b4f71a2f68..f3ed7ff57ed 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit 3b4f71a2f6854b91554dc38597c03f88f91b4966 +Subproject commit f3ed7ff57ed494367d54d405b461872efa520124 From b1a9f96bafedcbd742836f862387ca398db40634 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Wed, 26 Feb 2025 13:00:46 -0800 Subject: [PATCH 181/223] Fix comment for SubscribeToAllTables (#256) ## Description of Changes Updates comment on `SubscribeToAllTables` since undefined behavior is not possible anymore. No code changes made in this patch. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs N/A ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing No code changes made in this patch. --- .../client/module_bindings/SpacetimeDBClient.g.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs index 7edc469d193..ddedb4b09d0 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs @@ -367,15 +367,6 @@ string[] querySqls /// Applications where these resources are a constraint /// should register more precise queries via Self.Subscribe /// in order to replicate only the subset of data which the client needs to function. - /// - /// This method should not be combined with Self.Subscribe on the same DbConnection. - /// A connection may either Self.Subscribe to particular queries, - /// or Self.SubscribeToAllTables, but not both. - /// Attempting to call Self.Subscribe - /// on a DbConnection that has previously used Self.SubscribeToAllTables, - /// or vice versa, may misbehave in any number of ways, - /// including dropping subscriptions, corrupting the client cache, or panicking. - /// public void SubscribeToAllTables() { // Make sure we use the legacy handle constructor here, even though there's only 1 query. From df1dcf2b04a14b853f5a3054150ef8f664610aeb Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Fri, 28 Feb 2025 10:39:09 -0800 Subject: [PATCH 182/223] Fix comment for SubscribeToAllTables (#259) ## Description of Changes Adds closing `` to end of comment. ## API No breaking changes ## Requires SpacetimeDB PRs N/A ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing Just fixing a comment. No tests required. --- .../quickstart/client/module_bindings/SpacetimeDBClient.g.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs index ddedb4b09d0..1cfb5647bcb 100644 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs @@ -367,6 +367,7 @@ string[] querySqls /// Applications where these resources are a constraint /// should register more precise queries via Self.Subscribe /// in order to replicate only the subset of data which the client needs to function. + /// public void SubscribeToAllTables() { // Make sure we use the legacy handle constructor here, even though there's only 1 query. From 25689c14bd4dc56243f7131065f0ab029e213c3b Mon Sep 17 00:00:00 2001 From: rekhoff Date: Mon, 3 Mar 2025 13:35:30 -0800 Subject: [PATCH 183/223] Update C# server and client quickstart examples to match tutorial document. (#258) # Description of Changes Update the C# server and client SDK quickstart-chat example to match the code presented in the tutorial, as of https://github.com/clockworklabs/spacetime-docs/pull/170 . Also renamed the directory from `quickstart` to `quickstart-chat` in order to be more specific. # API and ABI breaking changes If this is an API or ABI breaking change, please apply the corresponding GitHub label. # Expected complexity level and risk 1 ## Requires SpacetimeDB PRs SpacetimeDB branch name: master com.clockworklabs.spacetimedbsdk: master # Testing *Describe any testing you've done, and any testing you'd like your reviewers to do, so that you're confident that all the changes work as expected!* - [x] Ran `quickstart-chat` C# server and C# client locally and: - Set my name. - Sent a message. - Restarted and viewed the message backlog. - Sent a few more messages. - Exited, deleted my local token, restarted and connected as a new identity. - Set my new identity's name. - Sent a message as my new identity. --------- Co-authored-by: Zeke Foppa Co-authored-by: John Detter Co-authored-by: james gilles --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 +- sdks/csharp/SpacetimeDB.ClientSDK.sln | 12 +- .../client/Program.cs | 152 +++--- .../client/README.md | 0 .../client/client.csproj | 0 .../Reducers/IdentityConnected.g.cs | 0 .../Reducers/IdentityDisconnected.g.cs | 0 .../module_bindings/Reducers/SendMessage.g.cs | 0 .../module_bindings/Reducers/SetName.g.cs | 0 .../module_bindings/SpacetimeDBClient.g.cs | 459 +++++++++++++++++ .../module_bindings/Tables/Message.g.cs | 0 .../client/module_bindings/Tables/User.g.cs | 0 .../client/module_bindings/Types/Message.g.cs | 0 .../client/module_bindings/Types/User.g.cs | 0 .../quickstart-chat/server/.gitignore | 2 + .../examples~/quickstart-chat/server/Lib.cs | 115 +++++ .../quickstart-chat/server/StdbModule.csproj | 20 + .../quickstart-chat/server/global.json | 6 + .../module_bindings/SpacetimeDBClient.g.cs | 460 ------------------ sdks/csharp/package.json | 2 +- .../{1.0.0-rc4.meta => 1.0.0.meta} | 2 +- .../{1.0.0-rc4 => 1.0.0}/analyzers.meta | 0 .../analyzers/dotnet.meta | 0 .../analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.0.0-rc4 => 1.0.0}/lib.meta | 0 .../lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 65024 -> 65024 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 sdks/csharp/tests~/tests.csproj | 2 +- 31 files changed, 703 insertions(+), 533 deletions(-) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/Program.cs (63%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/README.md (100%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/client.csproj (100%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/module_bindings/Reducers/IdentityConnected.g.cs (100%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/module_bindings/Reducers/IdentityDisconnected.g.cs (100%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/module_bindings/Reducers/SendMessage.g.cs (100%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/module_bindings/Reducers/SetName.g.cs (100%) create mode 100644 sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/module_bindings/Tables/Message.g.cs (100%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/module_bindings/Tables/User.g.cs (100%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/module_bindings/Types/Message.g.cs (100%) rename sdks/csharp/examples~/{quickstart => quickstart-chat}/client/module_bindings/Types/User.g.cs (100%) create mode 100644 sdks/csharp/examples~/quickstart-chat/server/.gitignore create mode 100644 sdks/csharp/examples~/quickstart-chat/server/Lib.cs create mode 100644 sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj create mode 100644 sdks/csharp/examples~/quickstart-chat/server/global.json delete mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4.meta => 1.0.0.meta} (77%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (91%) mode change 100755 => 100644 rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/lib/netstandard2.1.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll (85%) mode change 100755 => 100644 rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc4 => 1.0.0}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index b966f650797..c3e8dd37086 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -17,7 +17,7 @@ README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk 1.0.0 - 1.0.0-rc4 + 1.0.0 $(DefaultItemExcludes);*~/** packages @@ -25,7 +25,7 @@ - + diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.sln b/sdks/csharp/SpacetimeDB.ClientSDK.sln index a417d3c74fe..b12de3f7394 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.sln +++ b/sdks/csharp/SpacetimeDB.ClientSDK.sln @@ -3,22 +3,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.6.33717.318 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples~\quickstart\client\client.csproj", "{8F33709C-DEE9-41CC-A477-D6128E3700B1}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpacetimeDB.ClientSDK", "SpacetimeDB.ClientSDK.csproj", "{242A8146-A58D-43E9-A2BD-31FFC6851AA6}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests~\tests.csproj", "{5CD31104-4719-4CE3-8D39-8BAE0B75C085}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples~\quickstart-chat\client\client.csproj", "{FE261832-1594-DE21-C8C8-2D525680CBD7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.Build.0 = Release|Any CPU {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU {242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -27,6 +23,10 @@ Global {5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Debug|Any CPU.Build.0 = Debug|Any CPU {5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Release|Any CPU.ActiveCfg = Release|Any CPU {5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Release|Any CPU.Build.0 = Release|Any CPU + {FE261832-1594-DE21-C8C8-2D525680CBD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE261832-1594-DE21-C8C8-2D525680CBD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE261832-1594-DE21-C8C8-2D525680CBD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE261832-1594-DE21-C8C8-2D525680CBD7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart-chat/client/Program.cs similarity index 63% rename from sdks/csharp/examples~/quickstart/client/Program.cs rename to sdks/csharp/examples~/quickstart-chat/client/Program.cs index 4327538caa2..b7fc352e93a 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/Program.cs @@ -5,30 +5,88 @@ using SpacetimeDB; using SpacetimeDB.Types; -const string HOST = "http://localhost:3000"; -const string DBNAME = "chatqs"; // our local client SpacetimeDB identity Identity? local_identity = null; + // declare a thread safe queue to store commands var input_queue = new ConcurrentQueue<(string Command, string Args)>(); void Main() { + // Initialize the `AuthToken` module AuthToken.Init(".spacetime_csharp_quickstart"); - - // TODO: just do `var conn = DbConnection...` when OnConnect signature is fixed. + // Builds and connects to the database DbConnection? conn = null; + conn = ConnectToDB(); + // Registers callbacks to run in response to database events. + RegisterCallbacks(conn); + // Declare a threadsafe cancel token to cancel the process loop + var cancellationTokenSource = new CancellationTokenSource(); + // Spawn a thread to call process updates and process commands + var thread = new Thread(() => ProcessThread(conn, cancellationTokenSource.Token)); + thread.Start(); + // Handles CLI input + InputLoop(); + // This signals the ProcessThread to stop + cancellationTokenSource.Cancel(); + thread.Join(); +} + +/// The URI of the SpacetimeDB instance hosting our chat module. +const string HOST = "http://localhost:3000"; + +/// The module name we chose when we published our module. +const string DBNAME = "quickstart-chat"; +/// Load credentials from a file and connect to the database. +DbConnection ConnectToDB() +{ + DbConnection? conn = null; conn = DbConnection.Builder() .WithUri(HOST) .WithModuleName(DBNAME) - //.WithToken(AuthToken.Token) - .OnConnect(OnConnect) + .WithToken(AuthToken.Token) + .OnConnect(OnConnected) .OnConnectError(OnConnectError) - .OnDisconnect(OnDisconnect) + .OnDisconnect(OnDisconnected) .Build(); + return conn; +} +/// Our `OnConnect` callback: save our credentials to a file. +void OnConnected(DbConnection conn, Identity identity, string authToken) +{ + local_identity = identity; + AuthToken.SaveToken(authToken); + + conn.SubscriptionBuilder() + .OnApplied(OnSubscriptionApplied) + .SubscribeToAllTables(); +} + +/// Our `OnConnectError` callback: print the error, then exit the process. +void OnConnectError(Exception e) +{ + Console.Write($"Error while connecting: {e}"); +} + +/// Our `OnDisconnect` callback: print a note, then exit the process. +void OnDisconnected(DbConnection conn, Exception? e) +{ + if (e != null) + { + Console.Write($"Disconnected abnormally: {e}"); + } + else + { + Console.Write($"Disconnected normally."); + } +} + +/// Register all the callbacks our app will use to respond to database events. +void RegisterCallbacks(DbConnection conn) +{ conn.Db.User.OnInsert += User_OnInsert; conn.Db.User.OnUpdate += User_OnUpdate; @@ -36,23 +94,12 @@ void Main() conn.Reducers.OnSetName += Reducer_OnSetNameEvent; conn.Reducers.OnSendMessage += Reducer_OnSendMessageEvent; - - // declare a threadsafe cancel token to cancel the process loop - var cancellationTokenSource = new CancellationTokenSource(); - - // spawn a thread to call process updates and process commands - var thread = new Thread(() => ProcessThread(conn, cancellationTokenSource.Token)); - thread.Start(); - - InputLoop(); - - // this signals the ProcessThread to stop - cancellationTokenSource.Cancel(); - thread.Join(); } +/// If the user has no set name, use the first 8 characters from their identity. string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()[..8]; +/// Our `User.OnInsert` callback: if the user is online, print a notification. void User_OnInsert(EventContext ctx, User insertedValue) { if (insertedValue.Online) @@ -61,6 +108,8 @@ void User_OnInsert(EventContext ctx, User insertedValue) } } +/// Our `User.OnUpdate` callback: +/// print a notification about name and status changes. void User_OnUpdate(EventContext ctx, User oldValue, User newValue) { if (oldValue.Name != newValue.Name) @@ -80,6 +129,18 @@ void User_OnUpdate(EventContext ctx, User oldValue, User newValue) } } +/// Our `Message.OnInsert` callback: print new messages. +void Message_OnInsert(EventContext ctx, Message insertedValue) +{ + // We are filtering out messages inserted during the subscription being applied, + // since we will be printing those in the OnSubscriptionApplied callback, + // where we will be able to first sort the messages before printing. + if (ctx.Event is not Event.SubscribeApplied) + { + PrintMessage(ctx.Db, insertedValue); + } +} + void PrintMessage(RemoteTables tables, Message message) { var sender = tables.User.Identity.Find(message.Sender); @@ -92,15 +153,7 @@ void PrintMessage(RemoteTables tables, Message message) Console.WriteLine($"{senderName}: {message.Text}"); } -void Message_OnInsert(EventContext ctx, Message insertedValue) -{ - - if (ctx.Event is not Event.SubscribeApplied) - { - PrintMessage(ctx.Db, insertedValue); - } -} - +/// Our `OnSetNameEvent` callback: print a warning if the reducer failed. void Reducer_OnSetNameEvent(ReducerEventContext ctx, string name) { var e = ctx.Event; @@ -110,6 +163,7 @@ void Reducer_OnSetNameEvent(ReducerEventContext ctx, string name) } } +/// Our `OnSendMessageEvent` callback: print a warning if the reducer failed. void Reducer_OnSendMessageEvent(ReducerEventContext ctx, string text) { var e = ctx.Event; @@ -119,34 +173,12 @@ void Reducer_OnSendMessageEvent(ReducerEventContext ctx, string text) } } -void OnConnect(DbConnection conn, Identity identity, string authToken) -{ - local_identity = identity; - AuthToken.SaveToken(authToken); - - var subscription = conn.SubscriptionBuilder() - .OnApplied(OnSubscriptionApplied) - .Subscribe(new string[] { - "SELECT * FROM user", - "SELECT * FROM message", - // It is legal to have redundant subscriptions. - // However, keep in mind that data will be sent over the wire multiple times, - // once for each subscriptions. This can cause slowdowns if you aren't careful. - "SELECT * FROM message" }); - - // You can also use SubscribeToAllTables, but it should be avoided if you have any large tables: - // conn.SubscriptionBuilder().OnApplied(OnSubscriptionApplied).SubscribeToAllTables(); - -} - -void OnConnectError(Exception e) -{ - -} - -void OnDisconnect(DbConnection conn, Exception? e) +/// Our `OnSubscriptionApplied` callback: +/// sort all past messages and print them in timestamp order. +void OnSubscriptionApplied(SubscriptionEventContext ctx) { - + Console.WriteLine("Connected"); + PrintMessagesInOrder(ctx.Db); } void PrintMessagesInOrder(RemoteTables tables) @@ -157,12 +189,7 @@ void PrintMessagesInOrder(RemoteTables tables) } } -void OnSubscriptionApplied(SubscriptionEventContext ctx) -{ - Console.WriteLine("Connected"); - PrintMessagesInOrder(ctx.Db); -} - +/// Our separate thread from main, where we can call process updates and process commands without blocking the main thread. void ProcessThread(DbConnection conn, CancellationToken ct) { try @@ -183,6 +210,7 @@ void ProcessThread(DbConnection conn, CancellationToken ct) } } +/// Read each line of standard input, and either set our name or send a message as appropriate. void InputLoop() { while (true) diff --git a/sdks/csharp/examples~/quickstart/client/README.md b/sdks/csharp/examples~/quickstart-chat/client/README.md similarity index 100% rename from sdks/csharp/examples~/quickstart/client/README.md rename to sdks/csharp/examples~/quickstart-chat/client/README.md diff --git a/sdks/csharp/examples~/quickstart/client/client.csproj b/sdks/csharp/examples~/quickstart-chat/client/client.csproj similarity index 100% rename from sdks/csharp/examples~/quickstart/client/client.csproj rename to sdks/csharp/examples~/quickstart-chat/client/client.csproj diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs similarity index 100% rename from sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs rename to sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs similarity index 100% rename from sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs rename to sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs similarity index 100% rename from sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs rename to sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs similarity index 100% rename from sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs rename to sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs new file mode 100644 index 00000000000..7738e22e2c0 --- /dev/null +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs @@ -0,0 +1,459 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + internal RemoteReducers(DbConnection conn, SetReducerFlags flags) : base(conn) => SetCallReducerFlags = flags; + internal readonly SetReducerFlags SetCallReducerFlags; + } + + public sealed partial class RemoteTables : RemoteTablesBase + { + public RemoteTables(DbConnection conn) + { + AddTable(Message = new(conn)); + AddTable(User = new(conn)); + } + } + + public sealed partial class SetReducerFlags { } + + public interface IRemoteDbContext : IDbContext { } + + public sealed class EventContext : IEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + + /// + /// The event that caused this callback to run. + /// + public readonly Event Event; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + + internal EventContext(DbConnection conn, Event Event) + { + this.conn = conn; + this.Event = Event; + } + } + + public sealed class ReducerEventContext : IReducerEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The reducer event that caused this callback to run. + /// + public readonly ReducerEvent Event; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + + internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) + { + this.conn = conn; + Event = reducerEvent; + } + } + + public sealed class ErrorContext : IErrorContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The Exception that caused this error callback to be run. + /// + public readonly Exception Event; + Exception IErrorContext.Event { + get { + return Event; + } + } + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + + internal ErrorContext(DbConnection conn, Exception error) + { + this.conn = conn; + Event = error; + } + } + + public sealed class SubscriptionEventContext : ISubscriptionEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + + internal SubscriptionEventContext(DbConnection conn) + { + this.conn = conn; + } + } + + /// + /// Builder-pattern constructor for subscription queries. + /// + public sealed class SubscriptionBuilder + { + private readonly IDbConnection conn; + + private event Action? Applied; + private event Action? Error; + + /// + /// Private API, use conn.SubscriptionBuilder() instead. + /// + public SubscriptionBuilder(IDbConnection conn) + { + this.conn = conn; + } + + /// + /// Register a callback to run when the subscription is applied. + /// + public SubscriptionBuilder OnApplied( + Action callback + ) + { + Applied += callback; + return this; + } + + /// + /// Register a callback to run when the subscription fails. + /// + /// Note that this callback may run either when attempting to apply the subscription, + /// in which case Self::on_applied will never run, + /// or later during the subscription's lifetime if the module's interface changes, + /// in which case Self::on_applied may have already run. + /// + public SubscriptionBuilder OnError( + Action callback + ) + { + Error += callback; + return this; + } + + /// + /// Subscribe to the following SQL queries. + /// + /// This method returns immediately, with the data not yet added to the DbConnection. + /// The provided callbacks will be invoked once the data is returned from the remote server. + /// Data from all the provided queries will be returned at the same time. + /// + /// See the SpacetimeDB SQL docs for more information on SQL syntax: + /// https://spacetimedb.com/docs/sql + /// + public SubscriptionHandle Subscribe( + string[] querySqls + ) => new(conn, Applied, Error, querySqls); + + /// + /// Subscribe to all rows from all tables. + /// + /// This method is intended as a convenience + /// for applications where client-side memory use and network bandwidth are not concerns. + /// Applications where these resources are a constraint + /// should register more precise queries via Self.Subscribe + /// in order to replicate only the subset of data which the client needs to function. + /// + /// This method should not be combined with Self.Subscribe on the same DbConnection. + /// A connection may either Self.Subscribe to particular queries, + /// or Self.SubscribeToAllTables, but not both. + /// Attempting to call Self.Subscribe + /// on a DbConnection that has previously used Self.SubscribeToAllTables, + /// or vice versa, may misbehave in any number of ways, + /// including dropping subscriptions, corrupting the client cache, or panicking. + /// + public void SubscribeToAllTables() + { + // Make sure we use the legacy handle constructor here, even though there's only 1 query. + // We drop the error handler, since it can't be called for legacy subscriptions. + new SubscriptionHandle( + conn, + Applied, + new string[] { "SELECT * FROM *" } + ); + } + } + + public sealed class SubscriptionHandle : SubscriptionHandleBase { + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle(IDbConnection conn, Action? onApplied, string[] querySqls) : base(conn, onApplied, querySqls) + { } + + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle( + IDbConnection conn, + Action? onApplied, + Action? onError, + string[] querySqls + ) : base(conn, onApplied, onError, querySqls) + { } + } + + public abstract partial class Reducer + { + private Reducer() { } + } + + public sealed class DbConnection : DbConnectionBase + { + public override RemoteTables Db { get; } + public readonly RemoteReducers Reducers; + public readonly SetReducerFlags SetReducerFlags = new(); + + public DbConnection() + { + Db = new(this); + Reducers = new(this, SetReducerFlags); + } + + protected override Reducer ToReducer(TransactionUpdate update) + { + var encodedArgs = update.ReducerCall.Args; + return update.ReducerCall.ReducerName switch { + "identity_connected" => BSATNHelpers.Decode(encodedArgs), + "identity_disconnected" => BSATNHelpers.Decode(encodedArgs), + "send_message" => BSATNHelpers.Decode(encodedArgs), + "set_name" => BSATNHelpers.Decode(encodedArgs), + var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; + } + + protected override IEventContext ToEventContext(Event Event) => + new EventContext(this, Event); + + protected override IReducerEventContext ToReducerEventContext(ReducerEvent reducerEvent) => + new ReducerEventContext(this, reducerEvent); + + protected override ISubscriptionEventContext MakeSubscriptionEventContext() => + new SubscriptionEventContext(this); + + protected override IErrorContext ToErrorContext(Exception exception) => + new ErrorContext(this, exception); + + protected override bool Dispatch(IReducerEventContext context, Reducer reducer) + { + var eventContext = (ReducerEventContext)context; + return reducer switch { + Reducer.IdentityConnected args => Reducers.InvokeIdentityConnected(eventContext, args), + Reducer.IdentityDisconnected args => Reducers.InvokeIdentityDisconnected(eventContext, args), + Reducer.SendMessage args => Reducers.InvokeSendMessage(eventContext, args), + Reducer.SetName args => Reducers.InvokeSetName(eventContext, args), + _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; + } + + public SubscriptionBuilder SubscriptionBuilder() => new(this); + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Tables/Message.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/Message.g.cs similarity index 100% rename from sdks/csharp/examples~/quickstart/client/module_bindings/Tables/Message.g.cs rename to sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/Message.g.cs diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Tables/User.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/User.g.cs similarity index 100% rename from sdks/csharp/examples~/quickstart/client/module_bindings/Tables/User.g.cs rename to sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/User.g.cs diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/Message.g.cs similarity index 100% rename from sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs rename to sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/Message.g.cs diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Types/User.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/User.g.cs similarity index 100% rename from sdks/csharp/examples~/quickstart/client/module_bindings/Types/User.g.cs rename to sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/User.g.cs diff --git a/sdks/csharp/examples~/quickstart-chat/server/.gitignore b/sdks/csharp/examples~/quickstart-chat/server/.gitignore new file mode 100644 index 00000000000..1746e3269ed --- /dev/null +++ b/sdks/csharp/examples~/quickstart-chat/server/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/sdks/csharp/examples~/quickstart-chat/server/Lib.cs b/sdks/csharp/examples~/quickstart-chat/server/Lib.cs new file mode 100644 index 00000000000..b00ac93a927 --- /dev/null +++ b/sdks/csharp/examples~/quickstart-chat/server/Lib.cs @@ -0,0 +1,115 @@ +using SpacetimeDB; + +public static partial class Module +{ + [Table(Name = "user", Public = true)] + public partial class User + { + [PrimaryKey] + public Identity Identity; + public string? Name; + public bool Online; + } + + [Table(Name = "message", Public = true)] + public partial class Message + { + public Identity Sender; + public Timestamp Sent; + public string Text = ""; + } + + [Reducer] + public static void SetName(ReducerContext ctx, string name) + { + name = ValidateName(name); + + var user = ctx.Db.user.Identity.Find(ctx.Sender); + if (user is not null) + { + user.Name = name; + ctx.Db.user.Identity.Update(user); + } + } + + /// Takes a name and checks if it's acceptable as a user's name. + private static string ValidateName(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new Exception("Names must not be empty"); + } + return name; + } + + [Reducer] + public static void SendMessage(ReducerContext ctx, string text) + { + text = ValidateMessage(text); + Log.Info(text); + ctx.Db.message.Insert( + new Message + { + Sender = ctx.Sender, + Text = text, + Sent = ctx.Timestamp, + } + ); + } + + /// Takes a message's text and checks if it's acceptable to send. + private static string ValidateMessage(string text) + { + if (string.IsNullOrEmpty(text)) + { + throw new ArgumentException("Messages must not be empty"); + } + return text; + } + + [Reducer(ReducerKind.ClientConnected)] + public static void ClientConnected(ReducerContext ctx) + { + Log.Info($"Connect {ctx.Sender}"); + var user = ctx.Db.user.Identity.Find(ctx.Sender); + + if (user is not null) + { + // If this is a returning user, i.e., we already have a `User` with this `Identity`, + // set `Online: true`, but leave `Name` and `Identity` unchanged. + user.Online = true; + ctx.Db.user.Identity.Update(user); + } + else + { + // If this is a new user, create a `User` object for the `Identity`, + // which is online, but hasn't set a name. + ctx.Db.user.Insert( + new User + { + Name = null, + Identity = ctx.Sender, + Online = true, + } + ); + } + } + + [Reducer(ReducerKind.ClientDisconnected)] + public static void ClientDisconnected(ReducerContext ctx) + { + var user = ctx.Db.user.Identity.Find(ctx.Sender); + + if (user is not null) + { + // This user should exist, so set `Online: false`. + user.Online = false; + ctx.Db.user.Identity.Update(user); + } + else + { + // User does not exist, log warning + Log.Warn("Warning: No user found for disconnected client."); + } + } +} \ No newline at end of file diff --git a/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj b/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj new file mode 100644 index 00000000000..8d732fd7f65 --- /dev/null +++ b/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + + wasi-wasm + enable + enable + + $(NoWarn);CS8981;IDE1006 + + + + + + + diff --git a/sdks/csharp/examples~/quickstart-chat/server/global.json b/sdks/csharp/examples~/quickstart-chat/server/global.json new file mode 100644 index 00000000000..4e550c173fd --- /dev/null +++ b/sdks/csharp/examples~/quickstart-chat/server/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.400", + "rollForward": "latestMinor" + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs deleted file mode 100644 index 1cfb5647bcb..00000000000 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs +++ /dev/null @@ -1,460 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteReducers : RemoteBase - { - internal RemoteReducers(DbConnection conn, SetReducerFlags flags) : base(conn) => SetCallReducerFlags = flags; - internal readonly SetReducerFlags SetCallReducerFlags; - } - - public sealed partial class RemoteTables : RemoteTablesBase - { - public RemoteTables(DbConnection conn) - { - AddTable(Message = new(conn)); - AddTable(User = new(conn)); - } - } - - public sealed partial class SetReducerFlags { } - - public interface IRemoteDbContext : IDbContext { } - - public sealed class EventContext : IEventContext, IRemoteDbContext - { - private readonly DbConnection conn; - - /// - /// The event that caused this callback to run. - /// - public readonly Event Event; - - /// - /// Access to tables in the client cache, which stores a read-only replica of the remote database state. - /// - /// The returned DbView will have a method to access each table defined by the module. - /// - public RemoteTables Db => conn.Db; - /// - /// Access to reducers defined by the module. - /// - /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, - /// plus methods for adding and removing callbacks on each of those reducers. - /// - public RemoteReducers Reducers => conn.Reducers; - /// - /// Access to setters for per-reducer flags. - /// - /// The returned SetReducerFlags will have a method to invoke, - /// for each reducer defined by the module, - /// which call-flags for the reducer can be set. - /// - public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - /// - /// Returns true if the connection is active, i.e. has not yet disconnected. - /// - public bool IsActive => conn.IsActive; - /// - /// Close the connection. - /// - /// Throws an error if the connection is already closed. - /// - public void Disconnect() - { - conn.Disconnect(); - } - /// - /// Start building a subscription. - /// - /// A builder-pattern constructor for subscribing to queries, - /// causing matching rows to be replicated into the client cache. - public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); - /// - /// Get the Identity of this connection. - /// - /// This method returns null if the connection was constructed anonymously - /// and we have not yet received our newly-generated Identity from the host. - /// - public Identity? Identity => conn.Identity; - /// - /// Get this connection's ConnectionId. - /// - public ConnectionId ConnectionId => conn.ConnectionId; - - internal EventContext(DbConnection conn, Event Event) - { - this.conn = conn; - this.Event = Event; - } - } - - public sealed class ReducerEventContext : IReducerEventContext, IRemoteDbContext - { - private readonly DbConnection conn; - /// - /// The reducer event that caused this callback to run. - /// - public readonly ReducerEvent Event; - - /// - /// Access to tables in the client cache, which stores a read-only replica of the remote database state. - /// - /// The returned DbView will have a method to access each table defined by the module. - /// - public RemoteTables Db => conn.Db; - /// - /// Access to reducers defined by the module. - /// - /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, - /// plus methods for adding and removing callbacks on each of those reducers. - /// - public RemoteReducers Reducers => conn.Reducers; - /// - /// Access to setters for per-reducer flags. - /// - /// The returned SetReducerFlags will have a method to invoke, - /// for each reducer defined by the module, - /// which call-flags for the reducer can be set. - /// - public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - /// - /// Returns true if the connection is active, i.e. has not yet disconnected. - /// - public bool IsActive => conn.IsActive; - /// - /// Close the connection. - /// - /// Throws an error if the connection is already closed. - /// - public void Disconnect() - { - conn.Disconnect(); - } - /// - /// Start building a subscription. - /// - /// A builder-pattern constructor for subscribing to queries, - /// causing matching rows to be replicated into the client cache. - public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); - /// - /// Get the Identity of this connection. - /// - /// This method returns null if the connection was constructed anonymously - /// and we have not yet received our newly-generated Identity from the host. - /// - public Identity? Identity => conn.Identity; - /// - /// Get this connection's ConnectionId. - /// - public ConnectionId ConnectionId => conn.ConnectionId; - - internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) - { - this.conn = conn; - Event = reducerEvent; - } - } - - public sealed class ErrorContext : IErrorContext, IRemoteDbContext - { - private readonly DbConnection conn; - /// - /// The Exception that caused this error callback to be run. - /// - public readonly Exception Event; - Exception IErrorContext.Event - { - get - { - return Event; - } - } - - /// - /// Access to tables in the client cache, which stores a read-only replica of the remote database state. - /// - /// The returned DbView will have a method to access each table defined by the module. - /// - public RemoteTables Db => conn.Db; - /// - /// Access to reducers defined by the module. - /// - /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, - /// plus methods for adding and removing callbacks on each of those reducers. - /// - public RemoteReducers Reducers => conn.Reducers; - /// - /// Access to setters for per-reducer flags. - /// - /// The returned SetReducerFlags will have a method to invoke, - /// for each reducer defined by the module, - /// which call-flags for the reducer can be set. - /// - public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - /// - /// Returns true if the connection is active, i.e. has not yet disconnected. - /// - public bool IsActive => conn.IsActive; - /// - /// Close the connection. - /// - /// Throws an error if the connection is already closed. - /// - public void Disconnect() - { - conn.Disconnect(); - } - /// - /// Start building a subscription. - /// - /// A builder-pattern constructor for subscribing to queries, - /// causing matching rows to be replicated into the client cache. - public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); - /// - /// Get the Identity of this connection. - /// - /// This method returns null if the connection was constructed anonymously - /// and we have not yet received our newly-generated Identity from the host. - /// - public Identity? Identity => conn.Identity; - /// - /// Get this connection's ConnectionId. - /// - public ConnectionId ConnectionId => conn.ConnectionId; - - internal ErrorContext(DbConnection conn, Exception error) - { - this.conn = conn; - Event = error; - } - } - - public sealed class SubscriptionEventContext : ISubscriptionEventContext, IRemoteDbContext - { - private readonly DbConnection conn; - - /// - /// Access to tables in the client cache, which stores a read-only replica of the remote database state. - /// - /// The returned DbView will have a method to access each table defined by the module. - /// - public RemoteTables Db => conn.Db; - /// - /// Access to reducers defined by the module. - /// - /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, - /// plus methods for adding and removing callbacks on each of those reducers. - /// - public RemoteReducers Reducers => conn.Reducers; - /// - /// Access to setters for per-reducer flags. - /// - /// The returned SetReducerFlags will have a method to invoke, - /// for each reducer defined by the module, - /// which call-flags for the reducer can be set. - /// - public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - /// - /// Returns true if the connection is active, i.e. has not yet disconnected. - /// - public bool IsActive => conn.IsActive; - /// - /// Close the connection. - /// - /// Throws an error if the connection is already closed. - /// - public void Disconnect() - { - conn.Disconnect(); - } - /// - /// Start building a subscription. - /// - /// A builder-pattern constructor for subscribing to queries, - /// causing matching rows to be replicated into the client cache. - public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); - /// - /// Get the Identity of this connection. - /// - /// This method returns null if the connection was constructed anonymously - /// and we have not yet received our newly-generated Identity from the host. - /// - public Identity? Identity => conn.Identity; - /// - /// Get this connection's ConnectionId. - /// - public ConnectionId ConnectionId => conn.ConnectionId; - - internal SubscriptionEventContext(DbConnection conn) - { - this.conn = conn; - } - } - - /// - /// Builder-pattern constructor for subscription queries. - /// - public sealed class SubscriptionBuilder - { - private readonly IDbConnection conn; - - private event Action? Applied; - private event Action? Error; - - /// - /// Private API, use conn.SubscriptionBuilder() instead. - /// - public SubscriptionBuilder(IDbConnection conn) - { - this.conn = conn; - } - - /// - /// Register a callback to run when the subscription is applied. - /// - public SubscriptionBuilder OnApplied( - Action callback - ) - { - Applied += callback; - return this; - } - - /// - /// Register a callback to run when the subscription fails. - /// - /// Note that this callback may run either when attempting to apply the subscription, - /// in which case Self::on_applied will never run, - /// or later during the subscription's lifetime if the module's interface changes, - /// in which case Self::on_applied may have already run. - /// - public SubscriptionBuilder OnError( - Action callback - ) - { - Error += callback; - return this; - } - - /// - /// Subscribe to the following SQL queries. - /// - /// This method returns immediately, with the data not yet added to the DbConnection. - /// The provided callbacks will be invoked once the data is returned from the remote server. - /// Data from all the provided queries will be returned at the same time. - /// - /// See the SpacetimeDB SQL docs for more information on SQL syntax: - /// https://spacetimedb.com/docs/sql - /// - public SubscriptionHandle Subscribe( - string[] querySqls - ) => new(conn, Applied, Error, querySqls); - - /// - /// Subscribe to all rows from all tables. - /// - /// This method is intended as a convenience - /// for applications where client-side memory use and network bandwidth are not concerns. - /// Applications where these resources are a constraint - /// should register more precise queries via Self.Subscribe - /// in order to replicate only the subset of data which the client needs to function. - /// - public void SubscribeToAllTables() - { - // Make sure we use the legacy handle constructor here, even though there's only 1 query. - // We drop the error handler, since it can't be called for legacy subscriptions. - new SubscriptionHandle( - conn, - Applied, - new string[] { "SELECT * FROM *" } - ); - } - } - - public sealed class SubscriptionHandle : SubscriptionHandleBase - { - /// - /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. - /// - public SubscriptionHandle(IDbConnection conn, Action? onApplied, string[] querySqls) : base(conn, onApplied, querySqls) - { } - - /// - /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. - /// - public SubscriptionHandle( - IDbConnection conn, - Action? onApplied, - Action? onError, - string[] querySqls - ) : base(conn, onApplied, onError, querySqls) - { } - } - - public abstract partial class Reducer - { - private Reducer() { } - } - - public sealed class DbConnection : DbConnectionBase - { - public override RemoteTables Db { get; } - public readonly RemoteReducers Reducers; - public readonly SetReducerFlags SetReducerFlags = new(); - - public DbConnection() - { - Db = new(this); - Reducers = new(this, SetReducerFlags); - } - - protected override Reducer ToReducer(TransactionUpdate update) - { - var encodedArgs = update.ReducerCall.Args; - return update.ReducerCall.ReducerName switch - { - "identity_connected" => BSATNHelpers.Decode(encodedArgs), - "identity_disconnected" => BSATNHelpers.Decode(encodedArgs), - "send_message" => BSATNHelpers.Decode(encodedArgs), - "set_name" => BSATNHelpers.Decode(encodedArgs), - var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") - }; - } - - protected override IEventContext ToEventContext(Event Event) => - new EventContext(this, Event); - - protected override IReducerEventContext ToReducerEventContext(ReducerEvent reducerEvent) => - new ReducerEventContext(this, reducerEvent); - - protected override ISubscriptionEventContext MakeSubscriptionEventContext() => - new SubscriptionEventContext(this); - - protected override IErrorContext ToErrorContext(Exception exception) => - new ErrorContext(this, exception); - - protected override bool Dispatch(IReducerEventContext context, Reducer reducer) - { - var eventContext = (ReducerEventContext)context; - return reducer switch - { - Reducer.IdentityConnected args => Reducers.InvokeIdentityConnected(eventContext, args), - Reducer.IdentityDisconnected args => Reducers.InvokeIdentityDisconnected(eventContext, args), - Reducer.SendMessage args => Reducers.InvokeSendMessage(eventContext, args), - Reducer.SetName args => Reducers.InvokeSetName(eventContext, args), - _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") - }; - } - - public SubscriptionBuilder SubscriptionBuilder() => new(this); - } -} diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index ce1b8f739f8..015b4e0a2a5 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.0.0-rc3", + "version": "1.0.0", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0.meta similarity index 77% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0.meta index db902e53c53..a0714721e1a 100644 --- a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4.meta +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c602172ef60d71f41a6a5e85cf41da1a +guid: ae5666f23a6d73c43b030a1b9ba5916b folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll old mode 100755 new mode 100644 similarity index 91% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index f3ebe96120fb88d80336eee7b5da484e5513364b..4f83b6223eaa920672114d07c7ce3f18286888ad GIT binary patch delta 1853 zcmXw)4Qx|Y6vxkfuVvrB)^25Q?`c06WR7g@w)#3|OqWg&2@VqpAuO?P{TSOAn_FTu zB737iAZm2nEP|j63&utfk}ffR#gZ}|s2Br^gAs~dqDxHF2nJ0|JojY0mv`>}{m%cM zd*1EGGiPLTMt=REU0tP=8YcDIW*^hdQofBDzX}&tOnujIe0N)?4W5@Yf%x3u&)U*7*xM%cuO_IHgbxxBri%w9pM5c*c!DuLX zmW0)6p7>wHL3#)|lSDtVlmM?POQMcN;&52ANn%|)#!kD7JRbC{Q$6Hqrfj?5{6vp6 zG@yngQ9nf44VX0)V=;>Q5uBS)Ba|H>ZsO{l_A#oQ!0b`}OOIB4R85j6L;O6&tmutv zI~=0}YM!!8rk-U{L6$|IvW)vvBg>+HCvrn^k;jAltm+}&P9%f`yCu>gA4C5J*$q94 zu^6dasvM!p5%f>15#i_Q9a`D6nxMH!QJLS|;i&yh%@VnY{!aTvS|v}b?!j@o`_x80F%qXnD4RieczP8$7WwJojPg2Yjh`q{? z&QiD3U47B+nR;eMBaSoFtMdp`M9c!0dK= zP7r=}r^99_&Qej|RVsL}RPfoIezw4u4NNnc|1i)#n$m*h!qZVMIt-JJk~T^2BYlD5 zJjN-_QX!(VLd*(M3|ELA!lX^oCh19v86p|dInp`OV8aT0VwZz`!O!ff!_WQNuEtSA zF)KyoNs6Z`#cwB5NzX_mM>y2GZg2M&nWZA7Zg|_mba{+?O1V%-Kq#v%qU``za5;$ zN8&?mxY6GYP1IwHtAszeO0*j!9j0g!F-cDfoqp}vn@=o1^VQqWw|&wSOg{JVfy$R6 zhtj)0`@FiTnL&fE!Q0@ikN5(uabL4P9&OR}7N6eTe$D`F#`xbAVUzijL3TR!_3 zf3@p_XyfdM!WCNEwPhqWJkr%YI5hMEzkGdn)1u94TeRU~+8gVO9(d%}C$A2^_fx@} zSn&QaCA4$gRfVq=eq)3$oqM$Gh~<73;0WI~cS5=+^MB{u>}p!O>5%2U(8%>%{ZsW2 z0UrdQ72-HHgCEBzw1AFh3lbf=p$SI=yf{YD8AFeb_kNryX6Z14Io782|tP delta 1849 zcmXw)Z%h++7{{Mqua*BgX`yo5Wrd1_p-92fGK?uH(P?7v#hhWhX}w+*icTeQTjs)H zHJi>v*>9R`#MuoEF&pzmP4vaKloT?UZp&ikqCl)G$+8z@W{cTeT(;+Vf=BMl_dd_} z_xzr_LeH8}tQqCpyY@FX56_I8(ZtsySNE*!e*(}AbO?BAAE|McdIXf>W#n&wmt~D@ zz3dV7VoDC9K9yI+9`UghHm4)_DK3#e&IQuDY{53Mm_8M}v0lu{PIH^{aa9u}V1?QQ zgHWfof(oV_H9N~Hs!yWd?UGD>Gj-qQ>MKmrMAS)m3m%kbm$jIE5{&9;&fMWufw)(g zvNx`mnW|S%H?K&-X?ZfDuO$lSu+yIsTFIf>Pa^4EQO)kSTLGa2TStXY~( z>igY8hqXLcg~Br{)Im{bPDR1zQ>`d8zX!Rg)^Ns)Jgs?|cQOeh!D*RvDWjO*uGB(8 zjV>!s%bgAGY+!y?Gbk_9`}ML}Ey-)gsIy$y@2-2KWtq%kzS}j+yX1M7JafgK1h=f} z^E$WaUOP?LV5eQe$W7VZ*Mpz+)xM6#gxcVs4j~6u9dvhLB)eT*4w}$nK8*gTT-EQd zJFY%N|Dl@aWS*0GM+tToDXJkiWX#wI!6XmtaPA59r|uJ<248@ zk=F*?PE+-iQvaG#;-OOF_Xhl8Nv=9DEehmM2Rer)^w4U`bgiZdBkW`BE%qnaPq8kd z-qh{oq@HqG6=IE)(+m;z7JG|*iZ#O|!#>A8#~z&6L7qS87FjuQumL~!pAT*vGF7XB zI;U7KSJ3}Xrh@O0NsfJvJycTCQ%O}1`?Zyn53!FhkFbw1x7epxFEd$W^|@4}05wTr#Q;HFh<$|BVq&pRkx!pJys+cBt$&5TxaHlm^ZYoROX|J%(#O91 zs;Vs@pvBkJ+|<0`h_R_L(C!bI!C0F=7HBbpMsRO19*vs5mgbldiw68LU%bs1Xfgch z#NEe=&p5vH6vWP5HvG0fi|2Lx#=m|a&GI4ew-e8LJj3{!2+NWC-pW(kKDaP-;AZ%v zb2sY$yZy%-l-l~DynFxHhUHTB)#VayaBOD$?YplJw3oe7BwX)flV`{0a%ip^UnQe+ zgCos_a^?J%vXuQ<5g;Xd<}ca6F8`UY74vC*!L2B#p;ZQQjXfLS2pF&l8X*Af;72tf z2r+0wAH%B_zBZ8U#WN03{4v3Yycz2To>5Fu)`!(LR9a(zKb_8P6-AGL-+!6*^y*)J J7bDFD{{w7M3}65N diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll old mode 100755 new mode 100644 similarity index 85% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll index 57edd578fcedaf35fa0e264e3312173f693e9a15..50bbeca6b3f12def8775541aff272ddf48327023 GIT binary patch delta 6503 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 b%b&dzTlQu0S5=h70byZXP zqfL>J4D3YfNG(N_Xb}{G+Hu#W7=ct_34!=CVI7GIsRH#Mw@$PU$Q4pm^$z7S-xK4? zkKcK}cjlWj=d8Wynolz3lgziD$?iOM?}wMaxhuNm^5Vl=ez7f5XH@u#Bek5p+_`;| zj?|_w{^{08Jy`2(xwCdY+8ediE(R{w7Nduww`x(#_SQ{5QYxx-zCXBhw&m6FXnrZW zZ~v+2h1!AdjZ|LWaZr`in}Lt3|Lo{f+f-*RQ5V#3K2f&>me8d&J)^4m3n7!_pAKxx zU8GuFqvWe7W=G^AH0*9e7=!k`*LZ_xfap=JoR<(fFn zkl9jbl6g;cs6tLfvc(8yB1vW<*?K0LQT>HXB&)?#J7JMbkxVgU#tTI#OTmAtP{O}}|8!tm&agr?s;Tc6s#I&_=kV)c*2{%D z{(Ob@OH6i@ufj$M{j$&?^ahhX{&kYq(an%~v(ThXljLgDp}vxTmrT?mCzNTKQSTQr zEpi?kabnmBi!Bv7x?+nQT`@#I$`^@twQwrI52r$O1STz#Psk@BpKDLZpTkMXOu`b$ z5`KwfiR8r=+2Tbq)s~q@RBwBg!YnOkDc6}?XL3DEKHpv^Gf#B^-?2m^R84z>>NWf~ z0+W0*_^-6Dg!~h=@gMB2Jh8JiBNw?H7Bg4Ed30q$b>|+OzQ81(;E&>;!!O}X1*bPR zosko*;>?nH7RSQ*;1qHT%yJodz#V==@|FBDwo8pIzAI@iVP;b)!AgD%Y23?NDFXnQ8rEG+cZ8N_!=2rBybRglb!EtW~y~ z;*?tD0;X`L1KV=b_*Ifs{3@ACVa;Q?I(h-UNPdyLgAHainAIS8EhP6=a-MRNa+7kC z@(n5HR#|A3j9Mof&8(A+X4c6@GwV3xb<#ej+6jwfie!pp_Jqvd+`iz1J3vOmNRjgOlWoID6o}z;F;$6RHXR7_60T+o!`BFsQDPYeid`P^;M| zlki*e7HN42+FN83b+kh_&>r1HtDIyqIhhrUuH7@YJ4$L(b9aSPPd3TclTFeq-6Y9L zSb_##gjHza9IQhJufhiO@H$kRWz7h7!Vx$r{8HX*mUFs@H3zT4>oD3PljAM&fOVoZ z9DymEga%%O7S2Hjy|7k!Sst^rP1ZEfLI?d#f2;JeaBi#o#&TOF@1fepeqiS|IZ%xr zL8s_R^hId5$+22|C#>YJQ;4@qL9bC-8nlBRnjLIq2TPzG+U;ONP=&XQ;ehgziP0LZ z(J4Ab8+64m@C-b9CA@!py?rGwf3Q_Smg_2r(^Zf^x@kd{Hfv-<1);-n=;e@nVyDOP ztgwQk+GVwDyHsOzSA~IY=jyRibc!xhH8=)mHaLZx#j!Z^IR2*IDZf8HQhJv4?XH24N>(H8CCa*wRD+#~CF998L+ zC1R*y3JtW-LDfeRYM8=upDbGLlSK`V?c?D>JG4W4s1EUfA7ZsbJpVBRO+lkmXrP52 zs(zW4?dNsTFD+vn4O3|PrGY_Pv_(7UaXeZL++GP$HNaj5WLk{YFog!r4@k@T0cq)Q zmIvfUc(fX11*l;8gI!0@lLL;o?EdvKVTsbVwRt`%ubwrlP9^s)wYiN#01B15EL67gz z>L{By$|j(ODKxM$dsLdu9+hSmYyPM-b7&9M-7EpqyJgW7ZJ>n?-=RI)qt!9y!meY| ztLvEb(m11)W6~^TV4#H#dZ>nF2|X;0H9Ca`T6~LkXop@NmS)St(#+$m3`;Nd88!s< zXDTvC85n4xgC53O8poPVz!a9XG$?CnV8|H!SuJfWj>U1%Lp4Hss7LtypE5AeLI>4x z?%#2lkUcKVvd5)ajMH^o+Guo2GDRD-L0jmchbo~x)PeH;hk=0>&L`4rK9Oe2iL~*F zY{gSmqbvdSC^rS2qEobi7CPvm8e=Zh!b*O0Oqz|3Nwbtfc}!Xwv>THK4(*{j!4fCL zkI@>f(J3_0LI*uuIU&7PPDn3xkE~P4-XqOo1{$W&-Xjex+CdN1N%7T5Hi3@O8m7>| z*^|<2_M|kkIP)i^mqUA~DyLWoYG_VL1B15EL67gz>NJ};&0N@ZTAFp8mS!4f^t3cf z(FR)RpoeO_!V=@cbX*oq(FR)R@Ev-2T-q#;OB;{x@mI#BnYx$NpoS?l&_V}2R1-Y^ zdO{lO2{r-C6Vj$UA#DuK?1VJ1BrT3ZJG6)DKH5VKQ)r-t4tkh9Q&*MnqB| z_>3&kbw-+LbP5esgSKdkcF;q0miAD?6qe7*zY7d{7H!eOq=84O3{Kdr($$ zXb;sxa$FS8m7Wp|EtCDe=6L={|eWkJ|~Q!hAA|{rLVm@ zb4OeHn`1wIbf9Ojx75G%`?vp`>G{Xs-hWO-6K7k(=K{~m zhXvt71NEMWn_pq1wukS%;rsbed%pIUcZ-FEd&k~cn7QM=AAWwrYghg_@rN})mS=PUQU@SS6i-`mpn@5W!H!P?hHqT|b*h3KuNzrVLPy4<~?w&jE2 z&5vdOpHS+t+W8M&ihf)B_=95jBx3i6Z?pS;Qf=Uk$3msy}c_ z4XLsk2)Z0by^Kr2dn9~6swTsKQ>rKU-JxCz-;*IF*`81x2$VS`)xR|J&#y-t+ireZ PvZ-%r>nCrAy{-Qr - + From e21566a4e2292e50b1d222862e184b83be33ebd5 Mon Sep 17 00:00:00 2001 From: james gilles Date: Tue, 4 Mar 2025 00:39:37 -0500 Subject: [PATCH 184/223] Update README (#260) ## Description of Changes Just link to the existing docs. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing --- sdks/csharp/README.md | 129 +----------------------------------------- 1 file changed, 3 insertions(+), 126 deletions(-) diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 7bf46ba7876..3a8797389d1 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -1,136 +1,13 @@ -# SpacetimeDB SDK for Unity Engine +# SpacetimeDB C# SDK ## Overview -This repository contains the C# and [Unity](https://unity.com/) SDKs for SpacetimeDB. The SDK allows to interact with the database server and is prepared to work with code generated from a SpacetimeDB backend code. +This repository contains the C# and [Unity](https://unity.com/) client SDKs for SpacetimeDB. These SDKs contain all the tools you need to build native clients for SpacetimeDB modules using C#. ## Documentation -The Unity SDK uses the same code as the C# SDK. You can find the documentation for the C# SDK in the [C# SDK Reference](https://spacetimedb.com/docs/sdks/c-sharp) +The Unity SDK uses the same code as the C# SDK. You can find the documentation for the C# SDK in the [C# SDK Reference](https://spacetimedb.com/docs/sdks/c-sharp). For a guided tutorial, see the [C# SDK Quickstart](https://spacetimedb.com/docs/sdks/c-sharp/quickstart). There is also a comprehensive Unity tutorial/demo available: - [Unity Tutorial](https://spacetimedb.com/docs/unity/part-1) Doc - [Unity Demo](https://github.com/clockworklabs/SpacetimeDBUnityTutorial) Repo - -## Installation - -### Unity Demo - -Download the [.unitypackage release](https://github.com/clockworklabs/SpacetimeDBUnityTutorial/releases) of our [Unity Part 1 tutorial](https://spacetimedb.com/docs/unity/part-1) demo that includes this SDK as a package manfiest requirement. - -### Standalone - -1. Open the package manager window in Unity. -2. Click the "(+)" button in the top-left corner and select "Add package from git URL". -3. Paste the following URL: `https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk.git` - -## Usage - -### SpacetimeDBNetworkManager - -The Unity SDK for SpacetimeDB requires that there is a `SpacetimeDBNetworkManager` component attached to a GameObject in the scene. The `UnityNetworkManager` component is responsible for connecting to SpacetimeDB and managing the connection. The `UnityNetworkManager` component is a singleton and there can only be one instance of it in the scene. - -### Connecting to SpacetimeDB - -To connect to SpacetimeDB, you need to call the `Connect` method on the `SpacetimeDBClient` class. The `Connect` method takes the following parameters: - -- `token`: The authentication token to use to connect to SpacetimeDB. This token is generated by the backend code and is used to authenticate the client. -- `hostName`: The hostname of the SpacetimeDB server. This is the same hostname that you use to connect to the SpacetimeDB web interface. -- `moduleAddress`: The address of the module to connect to. This is the same address that you use to connect to the SpacetimeDB web interface. -- `sslEnabled`: Whether to use SSL to connect to SpacetimeDB. This is the same value that you use to connect to the SpacetimeDB web interface. - -Example: - -```csharp -using SpacetimeDB; - -SpacetimeDBClient.instance.Connect(TOKEN, HOST, DBNAME, SSL_ENABLED); -``` - -### AuthToken - -The `AuthToken` class is an optional helper class that can be used to store the local client's authentication token locally in the Unity PlayerPrefs. - -Example: - -```csharp -using SpacetimeDB; - -// called when we receive the client identity from SpacetimeDB -SpacetimeDBClient.instance.onIdentityReceived += (token, identity, address) => { - AuthToken.SaveToken(token); - local_identity = identity; -}; - -SpacetimeDBClient.instance.Connect(AuthToken.Token, hostName, moduleAddress, sslEnabled); -``` - -### Subscribing to tables - -To subscribe to a table, you need to call the `Subscribe` method on the `SpacetimeDBClient` class. The `Subscribe` method takes a list of queries as a parameter. The queries are the same queries that you use to subscribe to tables in the SpacetimeDB web interface. - -### Listening to events - -To listen to events, you need to register callbacks on the `SpacetimeDBClient` class. The following callbacks are available: - -- `onConnect`: Called when the client connects to SpacetimeDB. -- `onConnectError`: Called when the client fails to connect to SpacetimeDB. -- `onDisconnect`: Called when the client disconnects from SpacetimeDB. -- `onIdentityReceived`: Called when the client receives its identity from SpacetimeDB. -- `onSubscriptionApplied`: Called when the client receives the initial data from SpacetimeDB after subscribing to tables. - -You can register for row update events on a table. To do this, you need to register callbacks on the table class. The following callbacks are available: - -- `OnInsert`: Called when a row is inserted into the table. -- `OnUpdate`: Called when a row is updated in the table. -- `OnBeforeDelete`: Called before a row is deleted from the table. -- `OnDelete`: Called when a row is deleted from the table. -- `OnRowUpdate`: Called when a row is inserted, updated, or deleted from the table. - -Example: - -```csharp -using SpacetimeDB.Types; - -PlayerComponent.OnInsert += PlayerComponent_OnInsert; -PlayerComponent.OnUpdate += PlayerComponent_OnUpdate; -PlayerComponent.OnDelete += PlayerComponent_OnDelete; -PlayerComponent.OnBeforeDelete += PlayerComponent_OnBeforeDelete; -PlayerComponent.OnRowUpdate += PlayerComponent_OnRowUpdate; -``` - -You can register for reducer call updates as well. - -- `OnREDUCEREvent`: Called when a reducer call is received from SpacetimeDB. (If a) you are subscribed to the table that the reducer modifies or b) You called the reducer and it failed) - -Example: - -```csharp -using SpacetimeDB.Types; - -Reducer.OnMovePlayerEvent += Reducer_OnMovePlayerEvent; -``` - -### Accessing the client cache - -The client cache is a local cache of the data that the client has received from SpacetimeDB. The client cache is automatically updated when the client receives updates from SpacetimeDB. - -When you run the CLI generate command, SpacetimeDB will automatically generate a class for each table in your database. These classes are generated in the `SpacetimeDB.Types` namespace. Each class contains a set of static methods that allow you to query the client cache. The following methods are available: - -- `int Count()`: Returns the number of rows in the table. -- `IEnumerable Iter()`: Returns an iterator over the table. -- `IEnumerable FilterByCOLUMN(ColumnValue)`: Filters the table by the specified column value. -- `TableRow? FindByCOLUMN(ColumnValue)`: Finds a single item by the specifed column value. -- `IEnumerable Query(Func)`: Filters the table with the specified predicate. - -### Calling Reducers - -To call a reducer, you need to call the autogenerated method on the `Reducer` class. The autogenerated method takes the reducer arguments as parameters. The reducer arguments are the same arguments that are expected in your server module. - -Example: - -```csharp -using SpacetimeDB.Types; - -Reducer.MovePlayer(new StdbVector2(0.0f, 0.0f), new StdbVector2(1.0f, 1.0f)); -``` From 60761bb952abca080e1cf7dc36d18840181ab5b1 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 4 Mar 2025 07:10:52 -0800 Subject: [PATCH 185/223] Bump versions to 1.0.0 (#253) ## Description of Changes This just bumps our package versions to be 1.0.0. ## API No breaking changes ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2283 ## Testsuite SpacetimeDB branch name: bfops/bump-version ## Testing Existing CI only. --------- Co-authored-by: Zeke Foppa Co-authored-by: John Detter Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> From 421256a77f7f2564471bb33e498e6b47d7cd6e6b Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 11 Mar 2025 20:57:10 -0700 Subject: [PATCH 186/223] Relax the version constraint on SpacetimeDB nuget package (#270) ## Description of Changes Relaxed this version number from `1.0.0` to `1.0.*` ## API No breaking changes. ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing Existing CI should run `dotnet test` and confirm that this is not broken. --------- Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index c3e8dd37086..9a4839ffd66 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -25,7 +25,7 @@ - + From bbdb0fd6d8d5b604eb586a6134c6ddf89a1c143b Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Tue, 11 Mar 2025 23:15:32 -0500 Subject: [PATCH 187/223] Minor Version Bump to 1.0.1 (#261) ## Description of Changes *Describe what has been changed, any new features or bug fixes* I've already pushed this out to nuget here: - We want to update our REAME on nuget.org because the README that we released as part of 1.0.1 was very much out of date. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* NA ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] The README is updated. Co-authored-by: John Detter --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 9a4839ffd66..53a5bd6bce4 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk - 1.0.0 - 1.0.0 + 1.0.1 + 1.0.1 $(DefaultItemExcludes);*~/** packages From 9523ba3d278d4fc480e1e8847e06c6045e448c81 Mon Sep 17 00:00:00 2001 From: rekhoff Date: Thu, 13 Mar 2025 16:50:18 -0700 Subject: [PATCH 188/223] Adds tests of GenericEqualityComparer (#271) Adds an additional test of the `GenericEqualityComparer` function for `Integer`, `String`, `Byte Array`, `Identity`, `User` and `TaggedEnum` type comparisons. This PR resolves additional checks as reported in by [Issue 230](https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/230) that where not-yet covered elsewhere. ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs No other PR are needed for this to work. ## Testsuite SpacetimeDB branch name: master ## Testing - [X] Locally ran `dotnet test` against the `tests.csproj` project and it passed all tests --- sdks/csharp/tests~/Tests.cs | 84 +++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 sdks/csharp/tests~/Tests.cs diff --git a/sdks/csharp/tests~/Tests.cs b/sdks/csharp/tests~/Tests.cs new file mode 100644 index 00000000000..7bc6590054d --- /dev/null +++ b/sdks/csharp/tests~/Tests.cs @@ -0,0 +1,84 @@ +using SpacetimeDB; +using SpacetimeDB.BSATN; +using SpacetimeDB.Types; + +public class Tests +{ + [Fact] + public static void GenericEqualityComparerCheck() + { + // Validates the behavior of the GenericEqualityComparer's Equals function + + // Byte Arrays + byte[] byteArray = new byte[10]; + byte[] byteArrayByRef = byteArray; + byte[] byteArrayByValue = new byte[10]; + byte[] byteArrayUnequalValue = new byte[01]; + + Assert.True(GenericEqualityComparer.Instance.Equals(byteArray, byteArrayByRef)); + Assert.True(GenericEqualityComparer.Instance.Equals(byteArray, byteArrayByValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(byteArray, byteArrayUnequalValue)); + + // Integers + int integer = 5; + int integerByValue = 5; + int integerUnequalValue = 7; + string integerAsDifferingType = "5"; + + Assert.True(GenericEqualityComparer.Instance.Equals(integer, integerByValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(integer, integerUnequalValue)); + // GenericEqualityComparer does not support to converting datatypes and will fail this test + Assert.False(GenericEqualityComparer.Instance.Equals(integer, integerAsDifferingType)); + + // String + string testString = "This is a test"; + string testStringByRef = testString; + string testStringByValue = "This is a test"; + string testStringUnequalValue = "This is not the same string"; + + Assert.True(GenericEqualityComparer.Instance.Equals(testString, testStringByRef)); + Assert.True(GenericEqualityComparer.Instance.Equals(testString, testStringByValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(testString, testStringUnequalValue)); + + // Note: We are limited to only [SpacetimeDB.Type] + + // Identity and User + Identity identity = Identity.From(Convert.FromBase64String("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=")); + Identity identityByRef = identity; + Identity identityByValue = Identity.From(Convert.FromBase64String("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=")); + Identity identityUnequalValue = Identity.From(Convert.FromBase64String("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=")); + + User testUser = new User { Identity = identity, Name = "name", Online = false }; + User testUserByRef = testUser; + User testUserByValue = new User { Identity = identity, Name = "name", Online = false }; + User testUserUnequalIdentityValue = new User { Identity = identityUnequalValue, Name = "name", Online = false }; + User testUserUnequalNameValue = new User { Identity = identity, Name = "unequalName", Online = false }; + User testUserUnequalOnlineValue = new User { Identity = identity, Name = "name", Online = true }; + + Assert.True(GenericEqualityComparer.Instance.Equals(identity, identityByRef)); + Assert.True(GenericEqualityComparer.Instance.Equals(identity, identityByValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(identity, identityUnequalValue)); + + Assert.True(GenericEqualityComparer.Instance.Equals(testUser, testUserByRef)); + Assert.True(GenericEqualityComparer.Instance.Equals(testUser, testUserByValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(testUser, testUserUnequalIdentityValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(testUser, testUserUnequalNameValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(testUser, testUserUnequalOnlineValue)); + + // TaggedEnum using Status record + Status statusCommitted = new Status.Committed(default); + Status statusCommittedByRef = statusCommitted; + Status statusCommittedByValue = new Status.Committed(default); + Status statusFailed = new Status.Failed("Failed"); + Status statusFailedByValue = new Status.Failed("Failed"); + Status statusFailedUnequalValue = new Status.Failed("unequalFailed"); + Status statusOutOfEnergy = new Status.OutOfEnergy(default); + + Assert.True(GenericEqualityComparer.Instance.Equals(statusCommitted, statusCommittedByRef)); + Assert.True(GenericEqualityComparer.Instance.Equals(statusCommitted, statusCommittedByValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(statusCommitted, statusFailed)); + Assert.True(GenericEqualityComparer.Instance.Equals(statusFailed, statusFailedByValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(statusFailed, statusFailedUnequalValue)); + Assert.False(GenericEqualityComparer.Instance.Equals(statusCommitted, statusOutOfEnergy)); + } +} \ No newline at end of file From 4d3f0a0edcbd2c8ac7ba7dbeac79da39008e935c Mon Sep 17 00:00:00 2001 From: rekhoff Date: Thu, 13 Mar 2025 18:53:03 -0700 Subject: [PATCH 189/223] Resolved 404 and references to deprecated tutorial repos. (#268) ## Description of Changes Updated two README docs: * README.md - Updated links to point to Blackholio repo and tutorial docs. * README.dotnet.md - Updated to point to new URL paths for C# SDK Quickstart and Reference docs. ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs N/A - Docs only change ## Testsuite N/A - Docs only change SpacetimeDB branch name: master ## Testing - [X] Clicked on each new link and confirm the browser can locate the new locations. --------- Co-authored-by: Zeke Foppa Co-authored-by: John Detter --- sdks/csharp/README.dotnet.md | 126 +---------------------------------- sdks/csharp/README.md | 3 +- 2 files changed, 3 insertions(+), 126 deletions(-) diff --git a/sdks/csharp/README.dotnet.md b/sdks/csharp/README.dotnet.md index 82c2fc47aad..749a371c540 100644 --- a/sdks/csharp/README.dotnet.md +++ b/sdks/csharp/README.dotnet.md @@ -6,128 +6,4 @@ This repository contains the [C#](https://learn.microsoft.com/en-us/dotnet/cshar ## Documentation -The C# SDK has a [Quick Start](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-quickstart-guide) guide and a [Reference](https://spacetimedb.com/docs/client-languages/csharp/csharp-sdk-reference). - -## Installation - -The SDK is available as a [NuGet Package](https://www.nuget.org/packages/SpacetimeDB.ClientSDK). To install it, follow these steps: - -1. Open the NuGet package manager in Visual Studio. -2. Search for `SpacetimeDB.ClientSDK`. -3. Click the install button. - -Alternatively, it can be installed on the command line using the `dotnet` command: - -```bash -dotnet add package SpacetimeDB.ClientSDK -``` - -## Usage - -### Access the SpacetimeDB Client - -The SpacetimeDB client is created automatically as a singleton and accessible via the `SpacetimeDBClient.instance` property. - -### Connecting to SpacetimeDB - -To connect to SpacetimeDB, you need to call the `Connect` method on the `SpacetimeDBClient` class. The `Connect` method takes the following parameters: - -- `token`: The authentication token to use to connect to SpacetimeDB. This token is generated by the backend code and is used to authenticate the client. -- `hostName`: The hostname of the SpacetimeDB server. This is the same hostname that you use to connect to the SpacetimeDB web interface. -- `moduleAddress`: The address of the module to connect to. This is the same address that you use to connect to the SpacetimeDB web interface. -- `sslEnabled`: Whether to use SSL to connect to SpacetimeDB. This is the same value that you use to connect to the SpacetimeDB web interface. - -Example: - -```csharp -using SpacetimeDB; - -SpacetimeDBClient.instance.Connect(TOKEN, HOST, DBNAME, SSL_ENABLED); -``` - -### AuthToken optional helper class - -The `AuthToken` class is a helper class that can be used to store the local client's authentication token locally to your user's home directory. - -```csharp -using SpacetimeDB; - -AuthToken.Init(".spacetime_csharp_quickstart"); - -SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME, SSL_ENABLED); - -void OnIdentityReceived(string authToken, Identity identity) -{ - local_identity = identity; - AuthToken.SaveToken(authToken); -} -SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived; -``` - -### Subscribing to tables - -To subscribe to a table, you need to call the `Subscribe` method on the `SpacetimeDBClient` class. The `Subscribe` method takes a list of queries as a parameter. The queries are the same queries that you use to subscribe to tables in the SpacetimeDB web interface. - -### Listening to events - -To listen to events, you need to register callbacks on the `SpacetimeDBClient` class. The following callbacks are available: - -- `onConnect`: Called when the client connects to SpacetimeDB. -- `onConnectError`: Called when the client fails to connect to SpacetimeDB. -- `onDisconnect`: Called when the client disconnects from SpacetimeDB. -- `onIdentityReceived`: Called when the client receives its identity from SpacetimeDB. -- `onSubscriptionApplied`: Called when the client receives the initial data from SpacetimeDB after subscribing to tables. - -You can register for row update events on a table. To do this, you need to register callbacks on the table class. The following callbacks are available: - -- `OnInsert`: Called when a row is inserted into the table. -- `OnUpdate`: Called when a row is updated in the table. -- `OnBeforeDelete`: Called before a row is deleted from the table. -- `OnDelete`: Called when a row is deleted from the table. - -Example: - -```csharp -using SpacetimeDB.Types; - -PlayerComponent.OnInsert += PlayerComponent_OnInsert; -PlayerComponent.OnUpdate += PlayerComponent_OnUpdate; -PlayerComponent.OnDelete += PlayerComponent_OnDelete; -PlayerComponent.OnBeforeDelete += PlayerComponent_OnBeforeDelete; -``` - -You can register for reducer call updates as well. - -- `OnREDUCEREvent`: Called when a reducer call is received from SpacetimeDB. (If a) you are subscribed to the table that the reducer modifies or b) You called the reducer and it failed) - -Example: - -```csharp -using SpacetimeDB.Types; - -Reducer.OnMovePlayerEvent += Reducer_OnMovePlayerEvent; -``` - -### Accessing the client cache - -The client cache is a local cache of the data that the client has received from SpacetimeDB. The client cache is automatically updated when the client receives updates from SpacetimeDB. - -When you run the CLI generate command, SpacetimeDB will automatically generate a class for each table in your database. These classes are generated in the `SpacetimeDB.Types` namespace. Each class contains a set of static methods that allow you to query the client cache. The following methods are available: - -- `int Count()`: Returns the number of rows in the table. -- `IEnumerable Iter()`: Returns an iterator over the table. -- `IEnumerable FilterByCOLUMN(ColumnValue)`: Filters the table by the specified column value. -- `TableRow? FindByCOLUMN(ColumnValue)`: Finds a single item by the specifed column value. -- `IEnumerable Query(Func)`: Filters the table with the specified predicate. - -### Calling Reducers - -To call a reducer, you need to call the autogenerated method on the `Reducer` class. The autogenerated method takes the reducer arguments as parameters. The reducer arguments are the same arguments that are expected in your server module. - -Example: - -```csharp -using SpacetimeDB.Types; - -Reducer.MovePlayer(new StdbVector2(0.0f, 0.0f), new StdbVector2(1.0f, 1.0f)); -``` +The C# SDK has a [Quick Start](https://spacetimedb.com/docs/sdks/c-sharp/quickstart) guide and a [Reference](https://spacetimedb.com/docs/sdks/c-sharp). diff --git a/sdks/csharp/README.md b/sdks/csharp/README.md index 3a8797389d1..6cd3173b73d 100644 --- a/sdks/csharp/README.md +++ b/sdks/csharp/README.md @@ -10,4 +10,5 @@ The Unity SDK uses the same code as the C# SDK. You can find the documentation f There is also a comprehensive Unity tutorial/demo available: - [Unity Tutorial](https://spacetimedb.com/docs/unity/part-1) Doc -- [Unity Demo](https://github.com/clockworklabs/SpacetimeDBUnityTutorial) Repo +- [Unity Demo](https://github.com/clockworklabs/Blackholio) Repo +- \ No newline at end of file From 23c2dc083f46b76e3c27412430cdc624c05d6a4b Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 13 Mar 2025 22:18:02 -0600 Subject: [PATCH 190/223] Update DLLs to 1.0.1 (#269) ## Description of Changes I don't know if the DLLs need updating, but updated the DLLs just in case. ## API Incorporate any chances in SpacetimeDB 1.0.1. There should be no breaking changes. ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite SpacetimeDB branch name: release/v1.0.1 ## Testing None. Will test in release. --------- Co-authored-by: Zeke Foppa --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 0 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 65024 -> 0 bytes .../{1.0.0.meta => 1.0.1.meta} | 0 .../{1.0.0 => 1.0.1}/analyzers.meta | 0 .../{1.0.0 => 1.0.1}/analyzers/dotnet.meta | 0 .../{1.0.0 => 1.0.1}/analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 0 -> 64512 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.0.0 => 1.0.1}/lib.meta | 0 .../{1.0.0 => 1.0.1}/lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 67584 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 12 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll delete mode 100644 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0.meta => 1.0.1.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.1}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.1}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.1}/analyzers/dotnet/cs.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.1}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.1}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.1}/lib/netstandard2.1.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0 => 1.0.1}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll deleted file mode 100644 index 4f83b6223eaa920672114d07c7ce3f18286888ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58368 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 X&ngc541Gr8-|bkH^YeuN2ORicbchKg diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll deleted file mode 100644 index 50bbeca6b3f12def8775541aff272ddf48327023..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65024 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 Date: Fri, 14 Mar 2025 14:38:42 -0700 Subject: [PATCH 191/223] Bump package version to 1.0.1 (#272) Updates package version to 1.0.1 ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs No specific PR needed ## Testsuite SpacetimeDB branch name: release/v1.0.1 ## Testing - [X] Confirmed Unity sees version as 1.0.1 after change --- sdks/csharp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 015b4e0a2a5..9f74cd32d39 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.0.0", + "version": "1.0.1", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From d4267b3904eb7936527028601ae79c46be396637 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 27 Mar 2025 17:04:47 -0700 Subject: [PATCH 192/223] Bump versions to 1.1.0 (#282) ## Description of Changes Bumped version numbers to 1.1.0. ## API - [ ] This is an API breaking change to the SDK No, this just updates to the latest version. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2518 ## Testsuite SpacetimeDB branch name: bfops/bump-version ## Testing - [x] Existing CI passes (when pointed at the corresponding SpacetimeDB branch) Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 6 +++--- .../examples~/quickstart-chat/server/StdbModule.csproj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 53a5bd6bce4..e55d9df374f 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk - 1.0.1 - 1.0.1 + 1.1.0 + 1.1.0 $(DefaultItemExcludes);*~/** packages @@ -25,7 +25,7 @@ - + diff --git a/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj b/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj index 8d732fd7f65..07c9f725689 100644 --- a/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj +++ b/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj @@ -14,7 +14,7 @@ - + From 3543132c7d379a865b65196230745758024c5583 Mon Sep 17 00:00:00 2001 From: james gilles Date: Fri, 28 Mar 2025 13:15:51 -0700 Subject: [PATCH 193/223] Fix for unsubscribe bug + regression tests (#264) ## Description of Changes This PR fixes one issue and adds regression tests for it, plus another issue. These regression tests are run on CI. You can also run them locally -- run a local spacetime instance and then `tools~/run-regression-tests.sh ../SpacetimeDB`). ### Issue 1: Unsubscribe is non-functional See https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/279. This was a coding mistake made during the rush to 1.0. It was easily fixed. ### Issue 2: Indexes not tracking deletes This was recently discovered by the BitCraft team. The problem was introduced in https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/commit/cefc727b7693fe97e3dd848fef2bb17bf20c8be6 which introduced `RemoteTableHandle.IndexBase`. This class stores a `Dictionary>` to allow fast filtering. It relies on `List.Remove` to remove elements from a list when a row delete is received. `List.Remove` relies on `Row.Equals` to determine when elements are equal. `Row.Equals` formerly was not implemented for `[SpacetimeDB.Type]`s or for generated Row types. So, this didn't work. Now it does: it was fixed by https://github.com/clockworklabs/SpacetimeDB/pull/239 . So all this PR does to address this issue is add a regression test. ## API - [x] This is an API breaking change to the SDK The interface IDbConnection was changed; however, this changed part of the interface is `internal`, so this should be entirely invisible to users. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/239 (merged) ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] Added a repro for both issues - [x] Added the repro to CI - [x] Fixed both issues --- sdks/csharp/.github/workflows/test.yml | 12 +- sdks/csharp/SpacetimeDB.ClientSDK.sln | 21 + .../regression-tests/client/Program.cs | 142 ++++++ .../regression-tests/client/client.csproj | 15 + .../client/module_bindings/Reducers/Add.g.cs | 68 +++ .../module_bindings/Reducers/Delete.g.cs | 61 +++ .../module_bindings/SpacetimeDBClient.g.cs | 463 ++++++++++++++++++ .../module_bindings/Tables/ExampleData.g.cs | 49 ++ .../module_bindings/Types/ExampleData.g.cs | 34 ++ .../regression-tests/server/.gitignore | 2 + .../examples~/regression-tests/server/Lib.cs | 29 ++ .../regression-tests/server/StdbModule.csproj | 14 + .../regression-tests/server/global.json | 6 + sdks/csharp/src/Event.cs | 13 +- sdks/csharp/src/SpacetimeDBClient.cs | 7 +- sdks/csharp/tools~/gen-quickstart.sh | 2 +- sdks/csharp/tools~/gen-regression-tests.sh | 9 + sdks/csharp/tools~/run-regression-tests.sh | 13 + sdks/csharp/tools~/update-against-stdb.sh | 1 + sdks/csharp/tools~/write-nuget-config.sh | 5 + sdks/csharp/unity-tests~ | 2 +- 21 files changed, 961 insertions(+), 7 deletions(-) create mode 100644 sdks/csharp/examples~/regression-tests/client/Program.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/client.csproj create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ExampleData.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/.gitignore create mode 100644 sdks/csharp/examples~/regression-tests/server/Lib.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/StdbModule.csproj create mode 100644 sdks/csharp/examples~/regression-tests/server/global.json create mode 100755 sdks/csharp/tools~/gen-regression-tests.sh create mode 100644 sdks/csharp/tools~/run-regression-tests.sh diff --git a/sdks/csharp/.github/workflows/test.yml b/sdks/csharp/.github/workflows/test.yml index 8a4b11e9a18..ef92098c090 100644 --- a/sdks/csharp/.github/workflows/test.yml +++ b/sdks/csharp/.github/workflows/test.yml @@ -53,9 +53,15 @@ jobs: # Run cheap .NET tests first. If those fail, no need to run expensive Unity tests. + - name: Setup dotnet + uses: actions/setup-dotnet@v3 + with: + global-json-file: SpacetimeDB~/modules/global.json + - name: Override NuGet packages run: | dotnet pack SpacetimeDB~/crates/bindings-csharp/BSATN.Runtime + dotnet pack SpacetimeDB~/crates/bindings-csharp/Runtime # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if @@ -81,6 +87,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - name: Cache Rust dependencies uses: Swatinem/rust-cache@v2 @@ -128,7 +135,10 @@ jobs: spacetime start & disown - - name: Publish module to SpacetimeDB + - name: Run regression tests + run: bash tools~/run-regression-tests.sh SpacetimeDB~ + + - name: Publish unity-tests module to SpacetimeDB working-directory: unity-tests~/server-rust run: | spacetime logout && spacetime login --server-issued-login local diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.sln b/sdks/csharp/SpacetimeDB.ClientSDK.sln index b12de3f7394..00993d7df3b 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.sln +++ b/sdks/csharp/SpacetimeDB.ClientSDK.sln @@ -9,6 +9,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests~\tests.cspro EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples~\quickstart-chat\client\client.csproj", "{FE261832-1594-DE21-C8C8-2D525680CBD7}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples~", "examples~", "{E0CADA48-79A1-4490-ACEC-698EC7D2AB43}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "regression-tests", "regression-tests", "{4434F63A-3300-476E-82F3-D672B83E68E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StdbModule", "examples~\regression-tests\server\StdbModule.csproj", "{A68A749E-CFE1-45CF-8BDA-929B2E677D72}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples~\regression-tests\client\client.csproj", "{5BB2A377-C44C-4310-8951-BB37F5EB8456}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +35,14 @@ Global {FE261832-1594-DE21-C8C8-2D525680CBD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {FE261832-1594-DE21-C8C8-2D525680CBD7}.Release|Any CPU.ActiveCfg = Release|Any CPU {FE261832-1594-DE21-C8C8-2D525680CBD7}.Release|Any CPU.Build.0 = Release|Any CPU + {A68A749E-CFE1-45CF-8BDA-929B2E677D72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A68A749E-CFE1-45CF-8BDA-929B2E677D72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A68A749E-CFE1-45CF-8BDA-929B2E677D72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A68A749E-CFE1-45CF-8BDA-929B2E677D72}.Release|Any CPU.Build.0 = Release|Any CPU + {5BB2A377-C44C-4310-8951-BB37F5EB8456}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BB2A377-C44C-4310-8951-BB37F5EB8456}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BB2A377-C44C-4310-8951-BB37F5EB8456}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BB2A377-C44C-4310-8951-BB37F5EB8456}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -34,4 +50,9 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {35C59D87-64E5-4A6C-B1D5-2241B946E847} EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {4434F63A-3300-476E-82F3-D672B83E68E8} = {E0CADA48-79A1-4490-ACEC-698EC7D2AB43} + {A68A749E-CFE1-45CF-8BDA-929B2E677D72} = {4434F63A-3300-476E-82F3-D672B83E68E8} + {5BB2A377-C44C-4310-8951-BB37F5EB8456} = {4434F63A-3300-476E-82F3-D672B83E68E8} + EndGlobalSection EndGlobal diff --git a/sdks/csharp/examples~/regression-tests/client/Program.cs b/sdks/csharp/examples~/regression-tests/client/Program.cs new file mode 100644 index 00000000000..78864ef75db --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/Program.cs @@ -0,0 +1,142 @@ +/// Regression tests run with a live server. +/// To run these, run a local SpacetimeDB via `spacetime start`, +/// then in a separate terminal run `tools~/run-regression-tests.sh PATH_TO_SPACETIMEDB_REPO_CHECKOUT`. +/// This is done on CI in .github/workflows/test.yml. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using SpacetimeDB; +using SpacetimeDB.Types; + +const string HOST = "http://localhost:3000"; +const string DBNAME = "btree-repro"; + +DbConnection ConnectToDB() +{ + DbConnection? conn = null; + conn = DbConnection.Builder() + .WithUri(HOST) + .WithModuleName(DBNAME) + .OnConnect(OnConnected) + .OnConnectError((err) => + { + throw err; + }) + .OnDisconnect((conn, err) => + { + if (err != null) + { + throw err; + } + else + { + throw new Exception("Unexpected disconnect"); + } + }) + .Build(); + return conn; +} + +uint waiting = 0; +bool applied = false; +SubscriptionHandle? handle = null; + +void OnConnected(DbConnection conn, Identity identity, string authToken) +{ + Log.Debug($"Connected to {DBNAME} on {HOST}"); + handle = conn.SubscriptionBuilder() + .OnApplied(OnSubscriptionApplied) + .OnError((ctx, err) => + { + throw err; + }) + .Subscribe(["SELECT * FROM ExampleData"]); + + conn.Reducers.OnAdd += (ReducerEventContext ctx, uint id, uint indexed) => + { + Log.Info("Got Add callback"); + waiting--; + ValidateBTreeIndexes(ctx); + }; + + conn.Reducers.OnDelete += (ReducerEventContext ctx, uint id) => + { + Log.Info("Got Delete callback"); + waiting--; + ValidateBTreeIndexes(ctx); + }; +} + +const uint MAX_ID = 10; + +// Test that indexes remain in sync with the expected table state when deletes are received. +// This used to fail, when row types did not correctly implement IEquatable. +void ValidateBTreeIndexes(IRemoteDbContext conn) +{ + Log.Debug("Checking indexes..."); + foreach (var data in conn.Db.ExampleData.Iter()) + { + Debug.Assert(conn.Db.ExampleData.Indexed.Filter(data.Id).Contains(data)); + } + var outOfIndex = conn.Db.ExampleData.Iter().ToHashSet(); + + for (uint i = 0; i < MAX_ID; i++) + { + foreach (var data in conn.Db.ExampleData.Indexed.Filter(i)) + { + Debug.Assert(outOfIndex.Contains(data)); + } + } + Log.Debug(" Indexes are good."); +} + +void OnSubscriptionApplied(SubscriptionEventContext context) +{ + // Do some operations that alter row state; + // we will check that everything is in sync in the callbacks for these reducer calls. + Log.Debug("Calling Add"); + waiting++; + context.Reducers.Add(1, 1); + applied = true; + + Log.Debug("Calling Delete"); + waiting++; + context.Reducers.Delete(1); + + Log.Debug("Calling Add"); + waiting++; + context.Reducers.Add(1, 1); + applied = true; + + // Now unsubscribe and check that the unsubscribe is actually applied. + Log.Debug("Calling Unsubscribe"); + waiting++; + handle?.UnsubscribeThen((ctx) => + { + Log.Debug("Received Unsubscribe"); + ValidateBTreeIndexes(ctx); + waiting--; + }); +} + +System.AppDomain.CurrentDomain.UnhandledException += (sender, args) => +{ + Log.Exception($"Unhandled exception: {sender} {args}"); + Environment.Exit(1); +}; +var db = ConnectToDB(); +Log.Info("Starting timer"); +const int TIMEOUT = 20; // seconds; +var start = DateTime.Now; +while (!applied || waiting > 0) +{ + db.FrameTick(); + Thread.Sleep(100); + if ((DateTime.Now - start).Seconds > TIMEOUT) + { + Log.Error($"Timeout, all events should have elapsed in {TIMEOUT} seconds!"); + Environment.Exit(1); + } +} +Log.Info("Success"); +Environment.Exit(0); \ No newline at end of file diff --git a/sdks/csharp/examples~/regression-tests/client/client.csproj b/sdks/csharp/examples~/regression-tests/client/client.csproj new file mode 100644 index 00000000000..c76a780a74d --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/client.csproj @@ -0,0 +1,15 @@ + + + + Exe + net8.0 + enable + enable + true + + + + + + + diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs new file mode 100644 index 00000000000..0820f6a20d3 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs @@ -0,0 +1,68 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void AddHandler(ReducerEventContext ctx, uint id, uint indexed); + public event AddHandler? OnAdd; + + public void Add(uint id, uint indexed) + { + conn.InternalCallReducer(new Reducer.Add(id, indexed), this.SetCallReducerFlags.AddFlags); + } + + public bool InvokeAdd(ReducerEventContext ctx, Reducer.Add args) + { + if (OnAdd == null) return false; + OnAdd( + ctx, + args.Id, + args.Indexed + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Add : Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + [DataMember(Name = "indexed")] + public uint Indexed; + + public Add( + uint Id, + uint Indexed + ) + { + this.Id = Id; + this.Indexed = Indexed; + } + + public Add() + { + } + + string IReducerArgs.ReducerName => "Add"; + } + } + + public sealed partial class SetReducerFlags + { + internal CallReducerFlags AddFlags; + public void Add(CallReducerFlags flags) => AddFlags = flags; + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs new file mode 100644 index 00000000000..f2fb372abfd --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs @@ -0,0 +1,61 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void DeleteHandler(ReducerEventContext ctx, uint id); + public event DeleteHandler? OnDelete; + + public void Delete(uint id) + { + conn.InternalCallReducer(new Reducer.Delete(id), this.SetCallReducerFlags.DeleteFlags); + } + + public bool InvokeDelete(ReducerEventContext ctx, Reducer.Delete args) + { + if (OnDelete == null) return false; + OnDelete( + ctx, + args.Id + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Delete : Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + + public Delete(uint Id) + { + this.Id = Id; + } + + public Delete() + { + } + + string IReducerArgs.ReducerName => "Delete"; + } + } + + public sealed partial class SetReducerFlags + { + internal CallReducerFlags DeleteFlags; + public void Delete(CallReducerFlags flags) => DeleteFlags = flags; + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs new file mode 100644 index 00000000000..01c6abeda59 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs @@ -0,0 +1,463 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + internal RemoteReducers(DbConnection conn, SetReducerFlags flags) : base(conn) => SetCallReducerFlags = flags; + internal readonly SetReducerFlags SetCallReducerFlags; + } + + public sealed partial class RemoteTables : RemoteTablesBase + { + public RemoteTables(DbConnection conn) + { + AddTable(ExampleData = new(conn)); + } + } + + public sealed partial class SetReducerFlags { } + + public interface IRemoteDbContext : IDbContext { } + + public sealed class EventContext : IEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + + /// + /// The event that caused this callback to run. + /// + public readonly Event Event; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + + internal EventContext(DbConnection conn, Event Event) + { + this.conn = conn; + this.Event = Event; + } + } + + public sealed class ReducerEventContext : IReducerEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The reducer event that caused this callback to run. + /// + public readonly ReducerEvent Event; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + + internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) + { + this.conn = conn; + Event = reducerEvent; + } + } + + public sealed class ErrorContext : IErrorContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The Exception that caused this error callback to be run. + /// + public readonly Exception Event; + Exception IErrorContext.Event + { + get + { + return Event; + } + } + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + + internal ErrorContext(DbConnection conn, Exception error) + { + this.conn = conn; + Event = error; + } + } + + public sealed class SubscriptionEventContext : ISubscriptionEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + + internal SubscriptionEventContext(DbConnection conn) + { + this.conn = conn; + } + } + + /// + /// Builder-pattern constructor for subscription queries. + /// + public sealed class SubscriptionBuilder + { + private readonly IDbConnection conn; + + private event Action? Applied; + private event Action? Error; + + /// + /// Private API, use conn.SubscriptionBuilder() instead. + /// + public SubscriptionBuilder(IDbConnection conn) + { + this.conn = conn; + } + + /// + /// Register a callback to run when the subscription is applied. + /// + public SubscriptionBuilder OnApplied( + Action callback + ) + { + Applied += callback; + return this; + } + + /// + /// Register a callback to run when the subscription fails. + /// + /// Note that this callback may run either when attempting to apply the subscription, + /// in which case Self::on_applied will never run, + /// or later during the subscription's lifetime if the module's interface changes, + /// in which case Self::on_applied may have already run. + /// + public SubscriptionBuilder OnError( + Action callback + ) + { + Error += callback; + return this; + } + + /// + public SubscriptionHandle Subscribe( + string[] querySqls + ) => new(conn, Applied, Error, querySqls); + + /// + /// Subscribe to all rows from all tables. + /// + /// This method is intended as a convenience + /// for applications where client-side memory use and network bandwidth are not concerns. + /// Applications where these resources are a constraint + /// should register more precise queries via Self.Subscribe + /// in order to replicate only the subset of data which the client needs to function. + /// + /// This method should not be combined with Self.Subscribe on the same DbConnection. + /// A connection may either Self.Subscribe to particular queries, + /// or Self.SubscribeToAllTables, but not both. + /// Attempting to call Self.Subscribe + /// on a DbConnection that has previously used Self.SubscribeToAllTables, + /// or vice versa, may misbehave in any number of ways, + /// including dropping subscriptions, corrupting the client cache, or panicking. + /// + public void SubscribeToAllTables() + { + // Make sure we use the legacy handle constructor here, even though there's only 1 query. + // We drop the error handler, since it can't be called for legacy subscriptions. + new SubscriptionHandle( + conn, + Applied, + new string[] { "SELECT * FROM *" } + ); + } + } + + public sealed class SubscriptionHandle : SubscriptionHandleBase + { + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle(IDbConnection conn, Action? onApplied, string[] querySqls) : base(conn, onApplied, querySqls) + { } + + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle( + IDbConnection conn, + Action? onApplied, + Action? onError, + string[] querySqls + ) : base(conn, onApplied, onError, querySqls) + { } + } + + public abstract partial class Reducer + { + private Reducer() { } + } + + public sealed class DbConnection : DbConnectionBase + { + public override RemoteTables Db { get; } + public readonly RemoteReducers Reducers; + public readonly SetReducerFlags SetReducerFlags = new(); + + public DbConnection() + { + Db = new(this); + Reducers = new(this, SetReducerFlags); + } + + protected override Reducer ToReducer(TransactionUpdate update) + { + var encodedArgs = update.ReducerCall.Args; + return update.ReducerCall.ReducerName switch + { + "Add" => BSATNHelpers.Decode(encodedArgs), + "Delete" => BSATNHelpers.Decode(encodedArgs), + var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; + } + + protected override IEventContext ToEventContext(Event Event) => + new EventContext(this, Event); + + protected override IReducerEventContext ToReducerEventContext(ReducerEvent reducerEvent) => + new ReducerEventContext(this, reducerEvent); + + protected override ISubscriptionEventContext MakeSubscriptionEventContext() => + new SubscriptionEventContext(this); + + protected override IErrorContext ToErrorContext(Exception exception) => + new ErrorContext(this, exception); + + protected override bool Dispatch(IReducerEventContext context, Reducer reducer) + { + var eventContext = (ReducerEventContext)context; + return reducer switch + { + Reducer.Add args => Reducers.InvokeAdd(eventContext, args), + Reducer.Delete args => Reducers.InvokeDelete(eventContext, args), + _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; + } + + public SubscriptionBuilder SubscriptionBuilder() => new(this); + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs new file mode 100644 index 00000000000..ac26997f2f5 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs @@ -0,0 +1,49 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class ExampleDataHandle : RemoteTableHandle + { + protected override string RemoteTableName => "ExampleData"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(ExampleData row) => row.Id; + + public IdUniqueIndex(ExampleDataHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + public sealed class IndexedIndex : BTreeIndexBase + { + protected override uint GetKey(ExampleData row) => row.Indexed; + + public IndexedIndex(ExampleDataHandle table) : base(table) { } + } + + public readonly IndexedIndex Indexed; + + internal ExampleDataHandle(DbConnection conn) : base(conn) + { + Id = new(this); + Indexed = new(this); + } + + protected override object GetPrimaryKey(ExampleData row) => row.Id; + } + + public readonly ExampleDataHandle ExampleData; + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ExampleData.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ExampleData.g.cs new file mode 100644 index 00000000000..d3b300f1283 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ExampleData.g.cs @@ -0,0 +1,34 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ExampleData + { + [DataMember(Name = "Id")] + public uint Id; + [DataMember(Name = "Indexed")] + public uint Indexed; + + public ExampleData( + uint Id, + uint Indexed + ) + { + this.Id = Id; + this.Indexed = Indexed; + } + + public ExampleData() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/server/.gitignore b/sdks/csharp/examples~/regression-tests/server/.gitignore new file mode 100644 index 00000000000..1746e3269ed --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/sdks/csharp/examples~/regression-tests/server/Lib.cs b/sdks/csharp/examples~/regression-tests/server/Lib.cs new file mode 100644 index 00000000000..3fb1973b3c6 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Lib.cs @@ -0,0 +1,29 @@ +// Server module for regression tests. +// Everything we're testing for happens SDK-side so this module is very uninteresting. + +using SpacetimeDB; + +public static partial class Module +{ + [SpacetimeDB.Table(Name = "ExampleData", Public = true)] + public partial struct ExampleData + { + [SpacetimeDB.PrimaryKey] + public uint Id; + + [SpacetimeDB.Index.BTree] + public uint Indexed; + } + + [SpacetimeDB.Reducer] + public static void Delete(ReducerContext ctx, uint id) + { + ctx.Db.ExampleData.Id.Delete(id); + } + + [SpacetimeDB.Reducer] + public static void Add(ReducerContext ctx, uint id, uint indexed) + { + ctx.Db.ExampleData.Insert(new ExampleData { Id = id, Indexed = indexed }); + } +} diff --git a/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj b/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj new file mode 100644 index 00000000000..479928b1fc9 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + wasi-wasm + enable + enable + + + + + + + diff --git a/sdks/csharp/examples~/regression-tests/server/global.json b/sdks/csharp/examples~/regression-tests/server/global.json new file mode 100644 index 00000000000..4e550c173fd --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.400", + "rollForward": "latestMinor" + } +} diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 6ad7c74c6ce..2cf605d6ff6 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -170,6 +170,8 @@ public class SubscriptionHandleBase : IS private readonly Action? onError; private Action? onEnded; + private QueryId? queryId; + private SubscriptionState state; /// @@ -231,6 +233,7 @@ protected SubscriptionHandleBase(IDbConnection conn, Action @@ -285,6 +288,14 @@ public void UnsubscribeThen(Action? onEnded) onEnded = (ctx) => { }; } this.onEnded = onEnded; + if (queryId == null) + { + Log.Warn("Unsubscribing from a query that was never submitted to the server does nothing."); + } + else + { + conn.Unsubscribe(queryId); + } } } } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 217275a9554..8b598bc22bf 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -109,7 +109,7 @@ public interface IDbConnection internal void AddOnDisconnect(WebSocket.CloseEventHandler cb); internal void LegacySubscribe(ISubscriptionHandle handle, string[] querySqls); - internal void Subscribe(ISubscriptionHandle handle, string[] querySqls); + internal QueryId? Subscribe(ISubscriptionHandle handle, string[] querySqls); internal void Unsubscribe(QueryId queryId); void FrameTick(); void Disconnect(); @@ -874,12 +874,12 @@ void IDbConnection.LegacySubscribe(ISubscriptionHandle handle, string[] querySql )); } - void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) + QueryId? IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) { if (!webSocket.IsConnected) { Log.Error("Cannot subscribe, not connected to server!"); - return; + return null; } var id = stats.SubscriptionRequestTracker.StartTrackingRequest(); @@ -895,6 +895,7 @@ void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) QueryId = new QueryId(queryId), } )); + return new QueryId(queryId); } /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("SELECT * FROM table WHERE sender = \"bob\""); diff --git a/sdks/csharp/tools~/gen-quickstart.sh b/sdks/csharp/tools~/gen-quickstart.sh index f16b9ee33f5..7485fc20e3b 100755 --- a/sdks/csharp/tools~/gen-quickstart.sh +++ b/sdks/csharp/tools~/gen-quickstart.sh @@ -6,4 +6,4 @@ STDB_PATH="$1" SDK_PATH="$(dirname "$0")/.." SDK_PATH="$(realpath "$SDK_PATH")" -cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- generate -y -l csharp -o "$SDK_PATH/examples~/quickstart/client/module_bindings" --project-path "$STDB_PATH/modules/quickstart-chat" +cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- generate -y -l csharp -o "$SDK_PATH/examples~/quickstart-chat/client/module_bindings" --project-path "$STDB_PATH/modules/quickstart-chat" diff --git a/sdks/csharp/tools~/gen-regression-tests.sh b/sdks/csharp/tools~/gen-regression-tests.sh new file mode 100755 index 00000000000..7338aa305b9 --- /dev/null +++ b/sdks/csharp/tools~/gen-regression-tests.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -ueo pipefail + +STDB_PATH="$1" +SDK_PATH="$(dirname "$0")/.." +SDK_PATH="$(realpath "$SDK_PATH")" + +cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/client/module_bindings" --project-path "$SDK_PATH/examples~/regression-tests/server" diff --git a/sdks/csharp/tools~/run-regression-tests.sh b/sdks/csharp/tools~/run-regression-tests.sh new file mode 100644 index 00000000000..43d6ee70555 --- /dev/null +++ b/sdks/csharp/tools~/run-regression-tests.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# This script requires a running local SpacetimeDB instance. + +set -ueo pipefail + +STDB_PATH="$1" +SDK_PATH="$(dirname "$0")/.." +SDK_PATH="$(realpath "$SDK_PATH")" + +"$SDK_PATH/tools~/gen-regression-tests.sh" "$STDB_PATH" +cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- publish -c -y -p "$SDK_PATH/examples~/regression-tests/server" btree-repro +cd "$SDK_PATH/examples~/regression-tests/client" && dotnet run -c Debug \ No newline at end of file diff --git a/sdks/csharp/tools~/update-against-stdb.sh b/sdks/csharp/tools~/update-against-stdb.sh index 7b5b556f2ab..b59e256c00c 100644 --- a/sdks/csharp/tools~/update-against-stdb.sh +++ b/sdks/csharp/tools~/update-against-stdb.sh @@ -11,6 +11,7 @@ SDK_PATH="$(realpath "$SDK_PATH")" "$SDK_PATH/tools~/write-nuget-config.sh" "$STDB_PATH" "$SDK_PATH/tools~/gen-client-api.sh" "$STDB_PATH" "$SDK_PATH/tools~/gen-quickstart.sh" "$STDB_PATH" +"$SDK_PATH/tools~/gen-btree-repro.sh" "$STDB_PATH" dotnet nuget locals all --clear dotnet pack "$STDB_PATH/crates/bindings-csharp" rm -rf "$SDK_PATH/packages" diff --git a/sdks/csharp/tools~/write-nuget-config.sh b/sdks/csharp/tools~/write-nuget-config.sh index 1655fc96bff..7849ed08a96 100755 --- a/sdks/csharp/tools~/write-nuget-config.sh +++ b/sdks/csharp/tools~/write-nuget-config.sh @@ -16,6 +16,8 @@ cat >nuget.config < + + @@ -23,6 +25,9 @@ cat >nuget.config < + + + diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index f3ed7ff57ed..c7797b68518 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit f3ed7ff57ed494367d54d405b461872efa520124 +Subproject commit c7797b68518fa1b2441adc4dde14b05ad484e8de From 468a6f142bd93491709760799c9e3607dccd1b05 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Sat, 12 Apr 2025 01:24:41 +0100 Subject: [PATCH 194/223] Fix warning message for failed to track reducer call (#280) ## Description of Changes *Describe what has been changed, any new features or bug fixes* - Fixes an issue that was reported in the discord where a user was connecting 2 clients to the same SpacetimeDB module with the same identity but different connection IDs. ## API - This is not breaking. ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing - [x] Build blackholio as a player build and launch it twice. You can play on both clients without seeing this warning in Player.log. --------- Co-authored-by: John Detter Co-authored-by: Zeke Foppa --- sdks/csharp/src/SpacetimeDBClient.cs | 2 +- ...s.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt | 3 +-- ...sts.VerifySampleDump_dumpName=SubscribeApplied.verified.txt | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 8b598bc22bf..ec780134bcc 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -788,7 +788,7 @@ private void OnMessageProcessComplete(ProcessedMessage processed) var hostDuration = (TimeSpan)transactionUpdate.TotalHostExecutionDuration; stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); var callerIdentity = transactionUpdate.CallerIdentity; - if (callerIdentity == Identity) + if (callerIdentity == Identity && transactionUpdate.CallerConnectionId == ConnectionId) { // This was a request that we initiated var requestId = transactionUpdate.ReducerCall.RequestId; diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 3c0606f9a43..6423d8c3bc0 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -514,8 +514,7 @@ }, Stats: { ReducerRequestTracker: { - sampleCount: 3, - requestsAwaitingResponse: 6 + requestsAwaitingResponse: 9 }, OneOffRequestTracker: {}, SubscriptionRequestTracker: { diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index 2f054c9e1c7..ee9ff063df7 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -659,8 +659,7 @@ }, Stats: { ReducerRequestTracker: { - sampleCount: 3, - requestsAwaitingResponse: 6 + requestsAwaitingResponse: 9 }, OneOffRequestTracker: {}, SubscriptionRequestTracker: {}, From 7d25b033e8d20cda37a2663d764c105001883ae3 Mon Sep 17 00:00:00 2001 From: james gilles Date: Mon, 14 Apr 2025 14:28:55 -0700 Subject: [PATCH 195/223] Switch to a better index data structure (#291) ## Description of Changes This should fix https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/290 ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing - [ ] CI Tests - [ ] Double-check bitcraft perf regression Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> --- sdks/csharp/src/Table.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index 9f10d632008..56c9e96d9ed 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -76,7 +76,7 @@ public abstract class BTreeIndexBase : IndexBase where Column : IEquatable, IComparable { // TODO: change to SortedDictionary when adding support for range queries. - private readonly Dictionary> cache = new(); + private readonly Dictionary> cache = new(); public BTreeIndexBase(RemoteTableHandle table) { From f24b0e8f869ce815358bde0938b49401330d23ff Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:48:05 -0700 Subject: [PATCH 196/223] Update DLLs to 1.1.0 (#288) ## Description of Changes Update DLLs to 1.1.0. ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2566 ## Testsuite SpacetimeDB branch name: release/v1.1.0 ## Testing We tested this with some bots --------- Co-authored-by: Zeke Foppa --- .../SpacetimeDB.BSATN.Runtime.dll | Bin 67584 -> 0 bytes .../{1.0.1.meta => 1.1.0.meta} | 0 .../{1.0.1 => 1.1.0}/analyzers.meta | 0 .../{1.0.1 => 1.1.0}/analyzers/dotnet.meta | 0 .../{1.0.1 => 1.1.0}/analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 64512 -> 64512 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.0.1 => 1.1.0}/lib.meta | 0 .../{1.0.1 => 1.1.0}/lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 67584 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 11 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1.meta => 1.1.0.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1 => 1.1.0}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1 => 1.1.0}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1 => 1.1.0}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1 => 1.1.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (98%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1 => 1.1.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1 => 1.1.0}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1 => 1.1.0}/lib/netstandard2.1.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.1 => 1.1.0}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll deleted file mode 100755 index 513d35e64a035609347f190d4ce7b4b62cee4cac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67584 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 agR#Nn%|8q|A!dWDD*PnExS8?Se?|Zm+GRWd delta 323 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 Date: Tue, 15 Apr 2025 16:09:43 -0700 Subject: [PATCH 197/223] Bump version in `package.json` (#293) ## Description of Changes Bump yet another version number. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing None --------- Co-authored-by: Zeke Foppa --- sdks/csharp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 9f74cd32d39..45c142a21a1 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.0.1", + "version": "1.1.0", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From f32754b3c7fe6ea33d3679e6aa792809bdb042e4 Mon Sep 17 00:00:00 2001 From: james gilles Date: Fri, 18 Apr 2025 08:59:08 -0700 Subject: [PATCH 198/223] Fix row deduplication issues (#294) ## Description of Changes Addresses https://github.com/clockworklabs/SpacetimeDBPrivate/issues/1585 There was an issue with row deduplication when a TransactionUpdate of the form: ``` + k1: v1 - k1: v1 - k1: v1 + k1: v2 ``` appeared, where `k1` is the primary key of a row and `v1`, `v2` are the full values of that row. The old manner of processing updates would see this as a no-op. I've updated the logic to handle this case correctly, at the cost of an extra equality comparison per row in an update. (Actually it's slightly cheaper than this, it skips the equality comparison if there is only row with a particular primary key in an update. This may help speed up processing of large updates e.g. chunk data in BitCraft.) ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing - [x] Added a failing test, then fixed it --- sdks/csharp/src/MultiDictionary.cs | 434 +++++++++++++++++---- sdks/csharp/tests~/MultiDictionaryTests.cs | 195 ++++++++- 2 files changed, 542 insertions(+), 87 deletions(-) diff --git a/sdks/csharp/src/MultiDictionary.cs b/sdks/csharp/src/MultiDictionary.cs index 1807496907e..8285aa18400 100644 --- a/sdks/csharp/src/MultiDictionary.cs +++ b/sdks/csharp/src/MultiDictionary.cs @@ -11,6 +11,9 @@ namespace SpacetimeDB /// A dictionary that may have multiple copies of a key-value pair. /// Note that a particular key only maps to one value -- it is a logical error /// to insert the same key with different values. + /// + /// You MUST use the MultiDictionary(IEqualityComparer keyComparer, IEqualityComparer valueComparer) + /// constructor to construct this -- it is a struct for performance reasons, but the default constructor creates an invalid state. ///

    /// /// @@ -71,7 +74,7 @@ public bool Add(TKey key, TValue value) Debug.Assert(key != null); if (RawDict.TryGetValue(key, out var result)) { - Debug.Assert(ValueComparer.Equals(value, result.Value), "Added key-value pair with mismatched value to existing data"); + Debug.Assert(ValueComparer.Equals(value, result.Value), $"Added key-value pair with mismatched value to existing data, {key} {value} {result.Value}"); RawDict[key] = (value, result.Multiplicity + 1); return false; } @@ -104,6 +107,23 @@ public bool Contains(KeyValuePair item) return false; } + /// + /// The number of times a key occurs in the multidictionary. + /// All of these occurrences must map to the same value. + /// + /// + /// + public uint Multiplicity(TKey key) => RawDict.ContainsKey(key) ? RawDict[key].Multiplicity : 0; + + /// + /// The value associated with a key. + /// + /// Throws if the key is not present. + /// + /// + /// + public TValue this[TKey key] => RawDict[key].Value; + /// /// Remove a key from the dictionary. /// @@ -172,24 +192,30 @@ public readonly IEnumerable> Entries public readonly IEnumerable> WillRemove(MultiDictionaryDelta delta) { var self = this; - return delta.Entries.Where(entry => + return delta.Entries.Where(their => { - var theirDelta = (int)entry.Value.Inserts - (int)entry.Value.Removes; - if (theirDelta >= 0) + if (their.Value.IsValueChange) { + // Value changes are translated to Updates, not removals. return false; } - if (self.RawDict.TryGetValue(entry.Key, out var mine)) + var theirNonValueChange = their.Value.NonValueChange; + if (theirNonValueChange.Delta >= 0) { - var resultMultiplicity = (int)mine.Multiplicity + theirDelta; - return resultMultiplicity <= 0; + // Adds can't result in removals. + return false; + } + if (self.RawDict.TryGetValue(their.Key, out var mine)) + { + var resultMultiplicity = (int)mine.Multiplicity + theirNonValueChange.Delta; + return resultMultiplicity <= 0; // if < 0, we have a problem, but that's caught in Apply. } else { - Log.Warn($"Want to remove row with key {entry.Key}, but it doesn't exist!"); + Log.Warn($"Want to remove row with key {their.Key}, but it doesn't exist!"); return false; } - }).Select(entry => new KeyValuePair(entry.Key, entry.Value.Value)); + }).Select(entry => new KeyValuePair(entry.Key, entry.Value.NonValueChange.Value)); } /// public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } internal ErrorContext(DbConnection conn, Exception error) { @@ -292,6 +320,14 @@ public void Disconnect() /// Get this connection's ConnectionId. /// public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } internal SubscriptionEventContext(DbConnection conn) { @@ -431,6 +467,7 @@ protected override Reducer ToReducer(TransactionUpdate update) { "Add" => BSATNHelpers.Decode(encodedArgs), "Delete" => BSATNHelpers.Decode(encodedArgs), + "ThrowError" => BSATNHelpers.Decode(encodedArgs), var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } @@ -454,10 +491,16 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) { Reducer.Add args => Reducers.InvokeAdd(eventContext, args), Reducer.Delete args => Reducers.InvokeDelete(eventContext, args), + Reducer.ThrowError args => Reducers.InvokeThrowError(eventContext, args), _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } public SubscriptionBuilder SubscriptionBuilder() => new(this); + public event Action OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } } } diff --git a/sdks/csharp/examples~/regression-tests/server/Lib.cs b/sdks/csharp/examples~/regression-tests/server/Lib.cs index 3fb1973b3c6..86a4ac55afc 100644 --- a/sdks/csharp/examples~/regression-tests/server/Lib.cs +++ b/sdks/csharp/examples~/regression-tests/server/Lib.cs @@ -26,4 +26,10 @@ public static void Add(ReducerContext ctx, uint id, uint indexed) { ctx.Db.ExampleData.Insert(new ExampleData { Id = id, Indexed = indexed }); } + + [SpacetimeDB.Reducer] + public static void ThrowError(ReducerContext ctx, string error) + { + throw new Exception(error); + } } diff --git a/sdks/csharp/tools~/update-against-stdb.sh b/sdks/csharp/tools~/update-against-stdb.sh index b59e256c00c..76d082b1058 100644 --- a/sdks/csharp/tools~/update-against-stdb.sh +++ b/sdks/csharp/tools~/update-against-stdb.sh @@ -11,7 +11,7 @@ SDK_PATH="$(realpath "$SDK_PATH")" "$SDK_PATH/tools~/write-nuget-config.sh" "$STDB_PATH" "$SDK_PATH/tools~/gen-client-api.sh" "$STDB_PATH" "$SDK_PATH/tools~/gen-quickstart.sh" "$STDB_PATH" -"$SDK_PATH/tools~/gen-btree-repro.sh" "$STDB_PATH" +"$SDK_PATH/tools~/gen-regression-tests.sh" "$STDB_PATH" dotnet nuget locals all --clear dotnet pack "$STDB_PATH/crates/bindings-csharp" rm -rf "$SDK_PATH/packages" From 5ad9baa3049ff575e87668c61f65c139352930d7 Mon Sep 17 00:00:00 2001 From: james gilles Date: Wed, 23 Apr 2025 20:44:16 -0700 Subject: [PATCH 205/223] Pre-decompress query updates (#302) This dramatically improves performance by avoiding the default implementation of BrotliStream.ReadByte() inherited from Stream, which allocates an array per byte read. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] Describe a test for this PR that you have completed --- sdks/csharp/src/MultiDictionary.cs | 4 ++-- sdks/csharp/src/SpacetimeDBClient.cs | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/src/MultiDictionary.cs b/sdks/csharp/src/MultiDictionary.cs index 8285aa18400..2225f336494 100644 --- a/sdks/csharp/src/MultiDictionary.cs +++ b/sdks/csharp/src/MultiDictionary.cs @@ -74,7 +74,7 @@ public bool Add(TKey key, TValue value) Debug.Assert(key != null); if (RawDict.TryGetValue(key, out var result)) { - Debug.Assert(ValueComparer.Equals(value, result.Value), $"Added key-value pair with mismatched value to existing data, {key} {value} {result.Value}"); + Debug.Assert(ValueComparer.Equals(value, result.Value)); RawDict[key] = (value, result.Multiplicity + 1); return false; } @@ -252,7 +252,7 @@ public void Apply(MultiDictionaryDelta delta, List 0) { diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index e9649b94358..b0c64123e35 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -314,7 +314,13 @@ private static ServerMessage DecompressDecodeMessage(byte[] bytes) _ => throw new InvalidOperationException("Unknown compression type"), }; - return new ServerMessage.BSATN().Read(new BinaryReader(decompressedStream)); + // TODO: consider pooling these. + // DO NOT TRY TO TAKE THIS OUT. The BrotliStream ReadByte() implementation allocates an array + // PER BYTE READ. You have to do it all at once to avoid that problem. + MemoryStream memoryStream = new MemoryStream(); + decompressedStream.CopyTo(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + return new ServerMessage.BSATN().Read(new BinaryReader(memoryStream)); } private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate update) @@ -338,7 +344,13 @@ private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate u throw new InvalidOperationException(); } - return new QueryUpdate.BSATN().Read(new BinaryReader(decompressedStream)); + // TODO: consider pooling these. + // DO NOT TRY TO TAKE THIS OUT. The BrotliStream ReadByte() implementation allocates an array + // PER BYTE READ. You have to do it all at once to avoid that problem. + MemoryStream memoryStream = new MemoryStream(); + decompressedStream.CopyTo(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + return new QueryUpdate.BSATN().Read(new BinaryReader(memoryStream)); } private static IEnumerable BsatnRowListIter(BsatnRowList list) From 875605878baa234ce841c00884e633c9b5ddcde4 Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:58:41 +0100 Subject: [PATCH 206/223] Version Bump 1.1.3 (#303) ## Description of Changes *Describe what has been changed, any new features or bug fixes* - Bumps version to 1.1.3 ## API This is not an API breaking change - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* - None ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* This is just a version bump, CI is sufficient. --- sdks/csharp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 5d31908a8d9..17f1f591f61 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.1.2", + "version": "1.1.3", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From 78f50007405792edbef2d35f4d65da5b1c8ba25d Mon Sep 17 00:00:00 2001 From: John Detter <4099508+jdetter@users.noreply.github.com> Date: Fri, 25 Apr 2025 17:53:04 +0100 Subject: [PATCH 207/223] Bump version to 1.1.4 (#307) ## Description of Changes *Describe what has been changed, any new features or bug fixes* - Bumps version to 1.1.4 ## API Not breaking - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* This is just a version bump --- sdks/csharp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 17f1f591f61..c406dcf7ceb 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.1.3", + "version": "1.1.4", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From 590e873a50a55173c7f604d9097d68d9ee642da3 Mon Sep 17 00:00:00 2001 From: james gilles Date: Sat, 26 Apr 2025 09:08:44 -0700 Subject: [PATCH 208/223] Significantly reduce small byte array allocations (#305) This purges the DbValue type, instead using row instances themselves as primary key for rows without primary keys. In addition, it instantiates only a single BinaryReader when reading updates for a table, rather than instantiating a BinaryReader and performing an array copy per-row of the table. Addresses https://github.com/clockworklabs/SpacetimeDBPrivate/issues/1633 ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] CI --------- Co-authored-by: rekhoff --- sdks/csharp/src/BSATNHelpers.cs | 18 +++ sdks/csharp/src/ListStream.cs | 91 +++++++++++++++ sdks/csharp/src/ListStream.cs.meta | 11 ++ sdks/csharp/src/SpacetimeDBClient.cs | 126 +++++++++------------ sdks/csharp/src/Table.cs | 80 ++++--------- sdks/csharp/tests~/MultiDictionaryTests.cs | 6 +- sdks/csharp/tests~/Tests.cs | 111 ++++++++++++------ 7 files changed, 283 insertions(+), 160 deletions(-) create mode 100644 sdks/csharp/src/ListStream.cs create mode 100644 sdks/csharp/src/ListStream.cs.meta diff --git a/sdks/csharp/src/BSATNHelpers.cs b/sdks/csharp/src/BSATNHelpers.cs index 59160657d31..562e112549f 100644 --- a/sdks/csharp/src/BSATNHelpers.cs +++ b/sdks/csharp/src/BSATNHelpers.cs @@ -5,9 +5,27 @@ namespace SpacetimeDB { public static class BSATNHelpers { + /// + /// Decode an element of a BSATN-serializable type from a list of bytes. + /// + /// This method performs several allocations. Prefer calling IStructuralReadWrite.Read(BinaryReader) when + /// deserializing many items from a buffer. + /// + /// + /// + /// public static T Decode(System.Collections.Generic.List bsatn) where T : IStructuralReadWrite, new() => Decode(bsatn.ToArray()); + /// + /// Decode an element of a BSATN-serializable type from a byte array. + /// + /// This method performs several allocations. Prefer calling IStructuralReadWrite.Read(BinaryReader) when + /// deserializing many items from a buffer. + /// + /// + /// + /// public static T Decode(byte[] bsatn) where T : IStructuralReadWrite, new() { using var stream = new MemoryStream(bsatn); diff --git a/sdks/csharp/src/ListStream.cs b/sdks/csharp/src/ListStream.cs new file mode 100644 index 00000000000..a50b78fd8c0 --- /dev/null +++ b/sdks/csharp/src/ListStream.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.IO; +using SpacetimeDB; + +/// +/// A stream that reads from an underlying list. +/// +/// Uses one less allocation than converting to a byte array and building a MemoryStream. +/// +internal class ListStream : Stream +{ + private List list; + private int pos; + + public ListStream(List data) + { + this.list = data; + this.pos = 0; + } + + public override bool CanRead => true; + + public override bool CanSeek => true; + + public override bool CanWrite => false; + + public override long Length => list.Count; + + public override long Position { get => pos; set => pos = (int)value; } + + public override void Flush() + { + // do nothing + } + + public override int Read(byte[] buffer, int offset, int count) + { + int listPos = pos; + int listEnd = Math.Min(list.Count, listPos + count); + int bufPos = offset; + int bufLength = buffer.Length; + for (; listPos < listEnd && bufPos < bufLength; listPos++, bufPos++) + { + buffer[bufPos] = list[listPos]; + } + pos = listPos; + return bufPos - offset; + } + + public override int Read(Span buffer) + { + int listPos = pos; + int listLength = list.Count; + int bufPos = 0; + int bufLength = buffer.Length; + for (; listPos < listLength && bufPos < bufLength; listPos++, bufPos++) + { + buffer[bufPos] = list[listPos]; + } + pos = listPos; + return bufPos; + } + + public override long Seek(long offset, SeekOrigin origin) + { + switch (origin) + { + case SeekOrigin.Begin: + pos = (int)offset; + break; + case SeekOrigin.Current: + pos += (int)offset; + break; + case SeekOrigin.End: + pos = (int)(Length + offset); + break; + } + return pos; + } + + public override void SetLength(long value) + { + throw new System.NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new System.NotSupportedException(); + } +} diff --git a/sdks/csharp/src/ListStream.cs.meta b/sdks/csharp/src/ListStream.cs.meta new file mode 100644 index 00000000000..38fa3ab6839 --- /dev/null +++ b/sdks/csharp/src/ListStream.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7877850cecd6e3649a8a315c438f443d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index b0c64123e35..cd8811be3bf 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -11,6 +11,7 @@ using SpacetimeDB.Internal; using SpacetimeDB.ClientApi; using Thread = System.Threading.Thread; +using System.Diagnostics; namespace SpacetimeDB @@ -211,11 +212,10 @@ struct UnprocessedMessage struct ProcessedDatabaseUpdate { - // Map: table handles -> (primary key -> DbValue). - // If a particular table has no primary key, the "primary key" is just a byte[] - // storing the BSATN encoding of the row. - // See Decode(...). - public Dictionary> Updates; + // Map: table handles -> (primary key -> IStructuralReadWrite). + // If a particular table has no primary key, the "primary key" is just the row itself. + // This is valid because any [SpacetimeDB.Type] automatically has a correct Equals and HashSet implementation. + public Dictionary> Updates; // Can't override the default constructor. Make sure you use this one! public static ProcessedDatabaseUpdate New() @@ -225,13 +225,11 @@ public static ProcessedDatabaseUpdate New() return result; } - public MultiDictionaryDelta DeltaForTable(IRemoteTableHandle table) + public MultiDictionaryDelta DeltaForTable(IRemoteTableHandle table) { if (!Updates.TryGetValue(table, out var delta)) { - // Make sure we use GenericEqualityComparer here, since it handles byte[]s and arbitrary primary key types - // correctly. - delta = new MultiDictionaryDelta(GenericEqualityComparer.Instance, DbValueComparer.Instance); + delta = new MultiDictionaryDelta(EqualityComparer.Default, EqualityComparer.Default); Updates[table] = delta; } @@ -265,18 +263,20 @@ struct ProcessedMessage /// If not, the BSATN for the entire row is used instead. /// /// - /// + /// /// /// - static DbValue Decode(IRemoteTableHandle table, byte[] bin, out object primaryKey) + static IStructuralReadWrite Decode(IRemoteTableHandle table, BinaryReader reader, out object primaryKey) { - var obj = table.DecodeValue(bin); + var obj = table.DecodeValue(reader); + // TODO(1.1): we should exhaustively check that GenericEqualityComparer works // for all types that are allowed to be primary keys. var primaryKey_ = table.GetPrimaryKey(obj); - primaryKey_ ??= bin; + primaryKey_ ??= obj; primaryKey = primaryKey_; - return new(obj, bin); + + return obj; } private static readonly Status Committed = new Status.Committed(default); @@ -353,24 +353,28 @@ private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate u return new QueryUpdate.BSATN().Read(new BinaryReader(memoryStream)); } - private static IEnumerable BsatnRowListIter(BsatnRowList list) - { - var rowsData = list.RowsData; - return list.SizeHint switch - { - RowSizeHint.FixedSize(var size) => Enumerable - .Range(0, rowsData.Count / size) - .Select(index => rowsData.Skip(index * size).Take(size).ToArray()), - - RowSizeHint.RowOffsets(var offsets) => offsets.Zip( - offsets.Skip(1).Append((ulong)rowsData.Count), - (start, end) => rowsData.Take((int)end).Skip((int)start).ToArray() - ), - - _ => throw new InvalidOperationException("Unknown RowSizeHint variant"), - }; - } + /// + /// Prepare to read a BsatnRowList. + /// + /// This could return an IEnumerable, but we return the reader and row count directly to avoid an allocation. + /// It is legitimate to repeatedly call IStructuralReadWrite.Read rowCount times on the resulting + /// BinaryReader: + /// Our decoding infrastructure guarantees that reading a value consumes the correct number of bytes + /// from the BinaryReader. (This is easy because BSATN doesn't have padding.) + /// + /// + /// A reader for the rows of the list and a count of rows. + private static (BinaryReader reader, int rowCount) ParseRowList(BsatnRowList list) => + ( + new BinaryReader(new ListStream(list.RowsData)), + list.SizeHint switch + { + RowSizeHint.FixedSize(var size) => list.RowsData.Count / size, + RowSizeHint.RowOffsets(var offsets) => offsets.Count, + _ => throw new NotImplementedException() + } + ); #if UNITY_WEBGL && !UNITY_EDITOR IEnumerator PreProcessMessages() @@ -455,9 +459,10 @@ void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, Pro { Log.Warn("Non-insert during an insert-only server message!"); } - foreach (var bin in BsatnRowListIter(qu.Inserts)) + var (insertReader, insertRowCount) = ParseRowList(qu.Inserts); + for (var i = 0; i < insertRowCount; i++) { - var obj = Decode(table, bin, out var pk); + var obj = Decode(table, insertReader, out var pk); delta.Add(pk, obj); } } @@ -473,9 +478,11 @@ void PreProcessDeleteOnlyTable(IRemoteTableHandle table, TableUpdate update, Pro { Log.Warn("Non-delete during a delete-only operation!"); } - foreach (var bin in BsatnRowListIter(qu.Deletes)) + + var (deleteReader, deleteRowCount) = ParseRowList(qu.Deletes); + for (var i = 0; i < deleteRowCount; i++) { - var obj = Decode(table, bin, out var pk); + var obj = Decode(table, deleteReader, out var pk); delta.Remove(pk, obj); } } @@ -491,14 +498,17 @@ void PreProcessTable(IRemoteTableHandle table, TableUpdate update, ProcessedData // Because we are accumulating into a MultiDictionaryDelta that will be applied all-at-once // to the table, it doesn't matter that we call Add before Remove here. - foreach (var bin in BsatnRowListIter(qu.Inserts)) + var (insertReader, insertRowCount) = ParseRowList(qu.Inserts); + for (var i = 0; i < insertRowCount; i++) { - var obj = Decode(table, bin, out var pk); + var obj = Decode(table, insertReader, out var pk); delta.Add(pk, obj); } - foreach (var bin in BsatnRowListIter(qu.Deletes)) + + var (deleteReader, deleteRowCount) = ParseRowList(qu.Deletes); + for (var i = 0; i < deleteRowCount; i++) { - var obj = Decode(table, bin, out var pk); + var obj = Decode(table, deleteReader, out var pk); delta.Remove(pk, obj); } } @@ -1002,9 +1012,13 @@ T[] LogAndThrow(string error) return LogAndThrow($"Mismatched result type, expected {typeof(T)} but got {resultTable.TableName}"); } - return BsatnRowListIter(resultTable.Rows) - .Select(BSATNHelpers.Decode) - .ToArray(); + var (resultReader, resultCount) = ParseRowList(resultTable.Rows); + var output = new T[resultCount]; + for (int i = 0; i < resultCount; i++) + { + output[i] = IStructuralReadWrite.Read(resultReader); + } + return output; } public bool IsActive => webSocket.IsConnected; @@ -1056,32 +1070,4 @@ public uint Next() return lastAllocated; } } - internal readonly struct DbValue - { - public readonly IStructuralReadWrite value; - public readonly byte[] bytes; - - public DbValue(IStructuralReadWrite value, byte[] bytes) - { - this.value = value; - this.bytes = bytes; - } - - // TODO: having a nice ToString here would give better way better errors when applying table deltas, - // but it's tricky to do that generically. - } - - /// - /// DbValue comparer that uses BSATN-encoded records to compare DbValues for equality. - /// - internal readonly struct DbValueComparer : IEqualityComparer - { - public static DbValueComparer Instance = new(); - - public bool Equals(DbValue x, DbValue y) => - ByteArrayComparer.Instance.Equals(x.bytes, y.bytes); - - public int GetHashCode(DbValue obj) => - ByteArrayComparer.Instance.GetHashCode(obj.bytes); - } } diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index 56c9e96d9ed..e3819fb7380 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading.Tasks; using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; namespace SpacetimeDB { @@ -23,14 +25,14 @@ public interface IRemoteTableHandle internal string RemoteTableName { get; } internal Type ClientTableType { get; } - internal IStructuralReadWrite DecodeValue(byte[] bytes); + internal IStructuralReadWrite DecodeValue(BinaryReader reader); /// /// Start applying a delta to the table. /// This is called for all tables before any updates are actually applied, allowing OnBeforeDelete to be invoked correctly. /// /// - internal void PreApply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta); + internal void PreApply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta); /// /// Apply a delta to the table. @@ -38,7 +40,7 @@ public interface IRemoteTableHandle /// Should fix up indices, to be ready for PostApply. /// /// - internal void Apply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta); + internal void Apply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta); /// /// Finish applying a delta to a table. @@ -138,10 +140,10 @@ public RemoteTableHandle(IDbConnection conn) : base(conn) { } // We store the BSATN encodings of objects next to their runtime representation. // This is memory-inefficient, but allows us to quickly compare objects when seeing if an update is a "real" // update or just a multiplicity change. - private readonly MultiDictionary Entries = new(GenericEqualityComparer.Instance, DbValueComparer.Instance); + private readonly MultiDictionary Entries = new(EqualityComparer.Default, EqualityComparer.Default); // The function to use for decoding a type value. - IStructuralReadWrite IRemoteTableHandle.DecodeValue(byte[] bytes) => BSATNHelpers.Decode(bytes); + IStructuralReadWrite IRemoteTableHandle.DecodeValue(BinaryReader reader) => IStructuralReadWrite.Read(reader); public delegate void RowEventHandler(EventContext context, Row row); public event RowEventHandler? OnInsert; @@ -153,7 +155,7 @@ public RemoteTableHandle(IDbConnection conn) : base(conn) { } public int Count => (int)Entries.CountDistinct; - public IEnumerable Iter() => Entries.Entries.Select(entry => (Row)entry.Value.value); + public IEnumerable Iter() => Entries.Entries.Select(entry => (Row)entry.Value); public Task RemoteQuery(string query) => conn.RemoteQuery($"SELECT {RemoteTableName}.* FROM {RemoteTableName} {query}"); @@ -206,21 +208,21 @@ void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructura } } - List> wasInserted = new(); - List<(object key, DbValue oldValue, DbValue newValue)> wasUpdated = new(); - List> wasRemoved = new(); + List> wasInserted = new(); + List<(object key, IStructuralReadWrite oldValue, IStructuralReadWrite newValue)> wasUpdated = new(); + List> wasRemoved = new(); - void IRemoteTableHandle.PreApply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta) + void IRemoteTableHandle.PreApply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta) { Debug.Assert(wasInserted.Count == 0 && wasUpdated.Count == 0 && wasRemoved.Count == 0, "Call Apply and PostApply before calling PreApply again"); foreach (var (_, value) in Entries.WillRemove(multiDictionaryDelta)) { - InvokeBeforeDelete(context, value.value); + InvokeBeforeDelete(context, value); } } - void IRemoteTableHandle.Apply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta) + void IRemoteTableHandle.Apply(IEventContext context, MultiDictionaryDelta multiDictionaryDelta) { try { @@ -241,40 +243,40 @@ void IRemoteTableHandle.Apply(IEventContext context, MultiDictionaryDelta - /// EqualityComparer used to compare primary keys. - /// - /// If the primary keys are byte arrays (i.e. if the table has no primary key), uses Internal.ByteArrayComparer. - /// Otherwise, falls back to .Equals(). - /// - /// TODO: we should test that this works for all of our supported primary key types. - /// - internal readonly struct GenericEqualityComparer : IEqualityComparer - { - public static GenericEqualityComparer Instance = new(); - - public new bool Equals(object x, object y) - { - if (x is byte[] x_ && y is byte[] y_) - { - return Internal.ByteArrayComparer.Instance.Equals(x_, y_); - } - return x.Equals(y); // MAKE SURE to use .Equals and not ==... that was a bug. - } - - public int GetHashCode(object obj) - { - if (obj is byte[] obj_) - { - return Internal.ByteArrayComparer.Instance.GetHashCode(obj_); - } - return obj.GetHashCode(); - } - - } } diff --git a/sdks/csharp/tests~/MultiDictionaryTests.cs b/sdks/csharp/tests~/MultiDictionaryTests.cs index 3a2d34177d3..5abba65af46 100644 --- a/sdks/csharp/tests~/MultiDictionaryTests.cs +++ b/sdks/csharp/tests~/MultiDictionaryTests.cs @@ -345,18 +345,18 @@ public void IdentitiesWorkAsPrimaryKeys() { // GenericEqualityComparer used to have a bug, this is a regression test for that. var identity = Identity.From(Convert.FromBase64String("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=")); - var hashSet = new HashSet(GenericEqualityComparer.Instance) + var hashSet = new HashSet(EqualityComparer.Default) { identity }; Debug.Assert(hashSet.Contains(identity)); - var dict = new MultiDictionary(GenericEqualityComparer.Instance, EqualityComparer.Default); + var dict = new MultiDictionary(EqualityComparer.Default, EqualityComparer.Default); dict.Add(identity, 3); dict.Add(identity, 3); - var delta = new MultiDictionaryDelta(GenericEqualityComparer.Instance, EqualityComparer.Default); + var delta = new MultiDictionaryDelta(EqualityComparer.Default, EqualityComparer.Default); delta.Remove(identity, 3); delta.Remove(identity, 3); var wasInserted = new List>(); diff --git a/sdks/csharp/tests~/Tests.cs b/sdks/csharp/tests~/Tests.cs index 7bc6590054d..3adb4970cba 100644 --- a/sdks/csharp/tests~/Tests.cs +++ b/sdks/csharp/tests~/Tests.cs @@ -1,3 +1,5 @@ +using System.Diagnostics; +using CsCheck; using SpacetimeDB; using SpacetimeDB.BSATN; using SpacetimeDB.Types; @@ -5,19 +7,10 @@ public class Tests { [Fact] - public static void GenericEqualityComparerCheck() + public static void DefaultEqualityComparerCheck() { - // Validates the behavior of the GenericEqualityComparer's Equals function - - // Byte Arrays - byte[] byteArray = new byte[10]; - byte[] byteArrayByRef = byteArray; - byte[] byteArrayByValue = new byte[10]; - byte[] byteArrayUnequalValue = new byte[01]; - - Assert.True(GenericEqualityComparer.Instance.Equals(byteArray, byteArrayByRef)); - Assert.True(GenericEqualityComparer.Instance.Equals(byteArray, byteArrayByValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(byteArray, byteArrayUnequalValue)); + // Sanity check on the behavior of the default EqualityComparer's Equals function w.r.t. spacetime types. + var comparer = EqualityComparer.Default; // Integers int integer = 5; @@ -25,10 +18,10 @@ public static void GenericEqualityComparerCheck() int integerUnequalValue = 7; string integerAsDifferingType = "5"; - Assert.True(GenericEqualityComparer.Instance.Equals(integer, integerByValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(integer, integerUnequalValue)); + Assert.True(comparer.Equals(integer, integerByValue)); + Assert.False(comparer.Equals(integer, integerUnequalValue)); // GenericEqualityComparer does not support to converting datatypes and will fail this test - Assert.False(GenericEqualityComparer.Instance.Equals(integer, integerAsDifferingType)); + Assert.False(comparer.Equals(integer, integerAsDifferingType)); // String string testString = "This is a test"; @@ -36,9 +29,9 @@ public static void GenericEqualityComparerCheck() string testStringByValue = "This is a test"; string testStringUnequalValue = "This is not the same string"; - Assert.True(GenericEqualityComparer.Instance.Equals(testString, testStringByRef)); - Assert.True(GenericEqualityComparer.Instance.Equals(testString, testStringByValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(testString, testStringUnequalValue)); + Assert.True(comparer.Equals(testString, testStringByRef)); + Assert.True(comparer.Equals(testString, testStringByValue)); + Assert.False(comparer.Equals(testString, testStringUnequalValue)); // Note: We are limited to only [SpacetimeDB.Type] @@ -55,15 +48,15 @@ public static void GenericEqualityComparerCheck() User testUserUnequalNameValue = new User { Identity = identity, Name = "unequalName", Online = false }; User testUserUnequalOnlineValue = new User { Identity = identity, Name = "name", Online = true }; - Assert.True(GenericEqualityComparer.Instance.Equals(identity, identityByRef)); - Assert.True(GenericEqualityComparer.Instance.Equals(identity, identityByValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(identity, identityUnequalValue)); + Assert.True(comparer.Equals(identity, identityByRef)); + Assert.True(comparer.Equals(identity, identityByValue)); + Assert.False(comparer.Equals(identity, identityUnequalValue)); - Assert.True(GenericEqualityComparer.Instance.Equals(testUser, testUserByRef)); - Assert.True(GenericEqualityComparer.Instance.Equals(testUser, testUserByValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(testUser, testUserUnequalIdentityValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(testUser, testUserUnequalNameValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(testUser, testUserUnequalOnlineValue)); + Assert.True(comparer.Equals(testUser, testUserByRef)); + Assert.True(comparer.Equals(testUser, testUserByValue)); + Assert.False(comparer.Equals(testUser, testUserUnequalIdentityValue)); + Assert.False(comparer.Equals(testUser, testUserUnequalNameValue)); + Assert.False(comparer.Equals(testUser, testUserUnequalOnlineValue)); // TaggedEnum using Status record Status statusCommitted = new Status.Committed(default); @@ -74,11 +67,65 @@ public static void GenericEqualityComparerCheck() Status statusFailedUnequalValue = new Status.Failed("unequalFailed"); Status statusOutOfEnergy = new Status.OutOfEnergy(default); - Assert.True(GenericEqualityComparer.Instance.Equals(statusCommitted, statusCommittedByRef)); - Assert.True(GenericEqualityComparer.Instance.Equals(statusCommitted, statusCommittedByValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(statusCommitted, statusFailed)); - Assert.True(GenericEqualityComparer.Instance.Equals(statusFailed, statusFailedByValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(statusFailed, statusFailedUnequalValue)); - Assert.False(GenericEqualityComparer.Instance.Equals(statusCommitted, statusOutOfEnergy)); + Assert.True(comparer.Equals(statusCommitted, statusCommittedByRef)); + Assert.True(comparer.Equals(statusCommitted, statusCommittedByValue)); + Assert.False(comparer.Equals(statusCommitted, statusFailed)); + Assert.True(comparer.Equals(statusFailed, statusFailedByValue)); + Assert.False(comparer.Equals(statusFailed, statusFailedUnequalValue)); + Assert.False(comparer.Equals(statusCommitted, statusOutOfEnergy)); + } + + [Fact] + public static void ListstreamWorks() + { + // Make sure ListStream behaves like MemoryStream. + + int listLength = 32; + Gen.Select(Gen.Byte.List[listLength], Gen.Int[0, 10].SelectMany(n => Gen.Int[0, listLength + 5].List[n].Select(list => + { + list.Sort(); + return list; + })), (list, cuts) => (list, cuts)).Sample((listCuts) => + { + var (list, cuts) = listCuts; + var listStream = new ListStream(list); + var memoryStream = new MemoryStream(list.ToArray()); + + for (var i = 0; i < cuts.Count - 1; i++) + { + var start = cuts[i]; + var end = cuts[i + 1]; + + var arr1 = new byte[end - start]; + Span span1 = arr1; + + var arr2 = new byte[end - start]; + Span span2 = arr2; + + var readList = listStream.Read(span1); + var readMemory = memoryStream.Read(span2); + Debug.Assert(readList == readMemory); + Debug.Assert(span1.SequenceEqual(span2)); + } + + listStream = new ListStream(list); + memoryStream = new MemoryStream(list.ToArray()); + + for (var i = 0; i < cuts.Count - 1; i++) + { + var start = cuts[i]; + var end = cuts[i + 1]; + var len = end - start; + + var arr1 = new byte[len + 3]; + var arr2 = new byte[len + 3]; + + // this is a janky way to choose the offset but I don't feel like plumbing in another randomized list + var readList = listStream.Read(arr1, len % 3, len); + var readMemory = memoryStream.Read(arr2, len % 3, len); + Debug.Assert(readList == readMemory); + Debug.Assert(arr1.SequenceEqual(arr2)); + } + }); } } \ No newline at end of file From 3dabd47bc88a7b7ba7d7d7252eca525077f9e1f4 Mon Sep 17 00:00:00 2001 From: joshua-spacetime Date: Mon, 28 Apr 2025 10:13:28 -0700 Subject: [PATCH 209/223] Add comment on the performance of LINQ for reading BSATN (#309) --- sdks/csharp/src/SpacetimeDBClient.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index cd8811be3bf..3f83e6969c9 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -356,12 +356,23 @@ private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate u /// /// Prepare to read a BsatnRowList. - /// + /// /// This could return an IEnumerable, but we return the reader and row count directly to avoid an allocation. /// It is legitimate to repeatedly call IStructuralReadWrite.Read rowCount times on the resulting /// BinaryReader: /// Our decoding infrastructure guarantees that reading a value consumes the correct number of bytes /// from the BinaryReader. (This is easy because BSATN doesn't have padding.) + /// + /// Previously here we were using LINQ to do what we're now doing with a custsom reader. + /// + /// Why are we no longer using LINQ? + /// + /// The calls in question, namely `Skip().Take()`, were fast under the Mono runtime, + /// but *much* slower when compiled AOT with IL2CPP. + /// Apparently Mono's JIT is smart enough to optimize away these LINQ ops, + /// resulting in a linear scan of the `BsatnRowList`. + /// Unfortunately IL2CPP could not, resulting in a quadratic scan. + /// See: https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/306 /// /// /// A reader for the rows of the list and a count of rows. From c813fb321d72a327898d85956072dc1e943f5cd8 Mon Sep 17 00:00:00 2001 From: james gilles Date: Mon, 12 May 2025 16:55:15 -0400 Subject: [PATCH 210/223] Fix list equals (#316) Update DLLs and generated code for SpacetimeDB 74ad4a14c --- .../Reducers/IdentityConnected.g.cs | 2 ++ .../Reducers/IdentityDisconnected.g.cs | 2 ++ .../module_bindings/Reducers/SendMessage.g.cs | 2 ++ .../module_bindings/Reducers/SetName.g.cs | 2 ++ .../module_bindings/SpacetimeDBClient.g.cs | 2 ++ .../module_bindings/Tables/Message.g.cs | 2 ++ .../client/module_bindings/Tables/User.g.cs | 2 ++ .../client/module_bindings/Types/Message.g.cs | 2 ++ .../client/module_bindings/Types/User.g.cs | 2 ++ .../client/module_bindings/Reducers/Add.g.cs | 2 ++ .../module_bindings/Reducers/Delete.g.cs | 2 ++ .../module_bindings/Reducers/ThrowError.g.cs | 2 ++ .../module_bindings/SpacetimeDBClient.g.cs | 2 ++ .../module_bindings/Tables/ExampleData.g.cs | 2 ++ .../module_bindings/Types/ExampleData.g.cs | 2 ++ .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 64512 -> 74240 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 67584 -> 68096 bytes .../SpacetimeDB/ClientApi/BsatnRowList.g.cs | 2 ++ .../SpacetimeDB/ClientApi/CallReducer.g.cs | 2 ++ .../SpacetimeDB/ClientApi/ClientMessage.g.cs | 2 ++ .../ClientApi/CompressableQueryUpdate.g.cs | 2 ++ .../SpacetimeDB/ClientApi/DatabaseUpdate.g.cs | 2 ++ .../SpacetimeDB/ClientApi/EnergyQuanta.g.cs | 2 ++ .../SpacetimeDB/ClientApi/IdentityToken.g.cs | 2 ++ .../ClientApi/InitialSubscription.g.cs | 2 ++ .../SpacetimeDB/ClientApi/OneOffQuery.g.cs | 2 ++ .../ClientApi/OneOffQueryResponse.g.cs | 2 ++ .../SpacetimeDB/ClientApi/OneOffTable.g.cs | 2 ++ .../src/SpacetimeDB/ClientApi/QueryId.g.cs | 2 ++ .../SpacetimeDB/ClientApi/QueryUpdate.g.cs | 2 ++ .../ClientApi/ReducerCallInfo.g.cs | 2 ++ .../SpacetimeDB/ClientApi/RowSizeHint.g.cs | 2 ++ .../SpacetimeDB/ClientApi/ServerMessage.g.cs | 2 ++ .../src/SpacetimeDB/ClientApi/Subscribe.g.cs | 2 ++ .../ClientApi/SubscribeApplied.g.cs | 2 ++ .../SpacetimeDB/ClientApi/SubscribeMulti.g.cs | 2 ++ .../ClientApi/SubscribeMultiApplied.g.cs | 2 ++ .../SpacetimeDB/ClientApi/SubscribeRows.g.cs | 2 ++ .../ClientApi/SubscribeSingle.g.cs | 2 ++ .../ClientApi/SubscriptionError.g.cs | 2 ++ .../SpacetimeDB/ClientApi/TableUpdate.g.cs | 2 ++ .../ClientApi/TransactionUpdate.g.cs | 2 ++ .../ClientApi/TransactionUpdateLight.g.cs | 2 ++ .../SpacetimeDB/ClientApi/Unsubscribe.g.cs | 2 ++ .../ClientApi/UnsubscribeApplied.g.cs | 2 ++ .../ClientApi/UnsubscribeMulti.g.cs | 2 ++ .../ClientApi/UnsubscribeMultiApplied.g.cs | 2 ++ .../SpacetimeDB/ClientApi/UpdateStatus.g.cs | 2 ++ sdks/csharp/tools~/gen-client-api.sh | 2 ++ sdks/csharp/tools~/gen-quickstart.sh | 1 + sdks/csharp/tools~/gen-regression-tests.sh | 1 + sdks/csharp/tools~/run-regression-tests.sh | 1 + 52 files changed, 97 insertions(+) diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs index 9cefef47ae5..d4705866624 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs index 7748f576d3f..2905db1a81d 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs index f138cacf43b..551618458a8 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs index bae09619d11..9b6d7cfcc70 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs index 40daa6e38fd..359ca6ab6da 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/Message.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/Message.g.cs index a0f160c8578..73c30ae33e5 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/Message.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/Message.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/User.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/User.g.cs index eed7485e116..8c5945a237f 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/User.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Tables/User.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/Message.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/Message.g.cs index 09ddde48c83..a386797d9b9 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/Message.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/Message.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/User.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/User.g.cs index 134f3332fd2..4dcf8eb52fb 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/User.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Types/User.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs index 200ebc1c43c..d08cb5c7389 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs index fdc083d7ae4..524036c0f3a 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ThrowError.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ThrowError.g.cs index 64685d4f872..ba42f46bf1c 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ThrowError.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ThrowError.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs index 0aa690dda66..f9e47e78db1 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs index ac26997f2f5..04ce1b321da 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ExampleData.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ExampleData.g.cs index d3b300f1283..40df9ba043d 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ExampleData.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ExampleData.g.cs @@ -1,6 +1,8 @@ // 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.1.1 (commit bc3d453e871c797c17fdab2d772019832cd9b73e). + #nullable enable using System; diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 8ae0c82ba73591ea328c138fbf08acdf6ea84a45..0a11560a1c7a98e118ea984ef2b2dd233c9fbbf5 100755 GIT binary patch literal 74240 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 o1!^I!@|*~jZf=KZ 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 Date: Thu, 15 May 2025 18:15:56 -0400 Subject: [PATCH 211/223] Faster deserialization (#315) ## Description of Changes Leverages https://github.com/clockworklabs/SpacetimeDB/pull/2725 to speed up row deserialization. Also updates DLLs for recent upstream fixes. Changes: - Uses much simpler code when deserializing enums, avoiding the use of reflection - Uses manually monomorphized row deserialization methods, which again avoid the use of reflection when constructing row objects ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2725 ## Testsuite SpacetimeDB branch name: jgilles/perf/faster-allocation ## Testing *Write instructions for a test that you performed for this PR* - [x] Blackholio - [x] Bitcraft (have done a basic test but no in-depth testing) --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 74240 -> 74240 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 68096 -> 68096 bytes sdks/csharp/src/Table.cs | 44 +++++++++++++++--- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 0a11560a1c7a98e118ea984ef2b2dd233c9fbbf5..31f403008023be2f3db29361f66014ab193a8d53 100755 GIT binary patch delta 27032 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

    M2pBHW=VZer`m}5` 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 MLGi7)uV38%10}s!tN;K2 delta 27011 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


    E9<$cxRohwrN3}h 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 literal 68096 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 + /// Base class for views of remote tables. + /// + /// + /// public abstract class RemoteTableHandle : RemoteBase, IRemoteTableHandle where EventContext : class, IEventContext where Row : class, IStructuralReadWrite, new() { + // Note: This should really be also parameterized with RowRW: IReadWrite, but that is a backwards- + // incompatible change. Instead, we call (IReadWrite)((IStructuralReadWrite)new Row()).GetSerializer(). + // Serializer.Read is faster than IStructuralReadWrite.Read since it's manually monomorphized + // and therefore avoids using reflection when initializing the row object. + public abstract class IndexBase where Column : IEquatable { @@ -134,16 +146,35 @@ public RemoteTableHandle(IDbConnection conn) : base(conn) { } // THE DATA IN THE TABLE. // The keys of this map are: // - Primary keys, if we have them. - // - Byte arrays, if we don't. + // - The entire row itself, if we don't. // But really, the keys are whatever SpacetimeDBClient chooses to give us. - // - // We store the BSATN encodings of objects next to their runtime representation. - // This is memory-inefficient, but allows us to quickly compare objects when seeing if an update is a "real" - // update or just a multiplicity change. private readonly MultiDictionary Entries = new(EqualityComparer.Default, EqualityComparer.Default); + private static IReadWrite? _serializer; + + /// + /// Serializer for the rows of this table. + /// + private static IReadWrite Serializer + { + get + { + // We can't just initialize this statically, because some BitCraft row types have static + // methods that read SpacetimeDBService.Conn.Db, and these fail if the connection is not + // there on the first load of those types (????). + // This should really be considered an error on their part, but for now we delay initializing any Rows until + // Serializer is actually read, that is, until a row actually needs to be deserialized -- + // at which point, the connection should be initialized. + if (_serializer == null) + { + _serializer = (IReadWrite)new Row().GetSerializer(); + } + return _serializer; + } + } + // The function to use for decoding a type value. - IStructuralReadWrite IRemoteTableHandle.DecodeValue(BinaryReader reader) => IStructuralReadWrite.Read(reader); + IStructuralReadWrite IRemoteTableHandle.DecodeValue(BinaryReader reader) => Serializer.Read(reader); public delegate void RowEventHandler(EventContext context, Row row); public event RowEventHandler? OnInsert; @@ -304,3 +335,4 @@ void IRemoteTableHandle.PostApply(IEventContext context) } } } +#nullable disable From 8bde94af327b5ca1081870031126caff30a9501b Mon Sep 17 00:00:00 2001 From: james gilles Date: Thu, 15 May 2025 18:41:37 -0400 Subject: [PATCH 212/223] Recreate #311 (#317) ## Description of Changes Recreating #311 using a branch in this repo in the hope of fixing the Unity build. ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing - [x] blackholio - [ ] bitcraft --------- Co-authored-by: Guribo --- sdks/csharp/src/WebSocket.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 71020bb7728..c6359dd46f1 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -50,6 +50,10 @@ public WebSocket(ConnectOptions options) public event OpenEventHandler? OnConnect; public event ConnectErrorEventHandler? OnConnectError; public event SendErrorEventHandler? OnSendError; + + /// + /// Called directly by background task (not on main thread!) + /// public event MessageEventHandler? OnMessage; public event CloseEventHandler? OnClose; @@ -337,7 +341,8 @@ await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, if (OnMessage != null) { var message = _receiveBuffer.Take(count).ToArray(); - dispatchQueue.Enqueue(() => OnMessage(message, startReceive)); + // directly invoke message handling + OnMessage(message, startReceive); } } catch (WebSocketException ex) From c03b962c07a0856f5802119b7216855613a9045f Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Wed, 21 May 2025 12:35:23 -0700 Subject: [PATCH 213/223] Bump versions to 1.1.5 (#320) ## Description of Changes Just bumping version numbers in preparation for a release. The Unity SDK and C# SDK had different version numbers. That seems confusing, so I bumped them both to 1.1.5. ## API No breaking changes ## Requires SpacetimeDB PRs None, afaik ## Testsuite SpacetimeDB branch name: master ## Testing None Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- sdks/csharp/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index b3ca7e8e206..e43b40b8be7 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk - 1.1.1 - 1.1.1 + 1.1.5 + 1.1.5 $(DefaultItemExcludes);*~/** packages diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index c406dcf7ceb..bbf39864b3c 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.1.4", + "version": "1.1.5", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From a198faddd5c1da9821e88ccedbad8091059e9a9b Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Thu, 22 May 2025 12:40:54 -0700 Subject: [PATCH 214/223] Update DLLs to 1.1.2 (#322) ## Description of Changes Update DLLs to the 1.1.2 versions that have been pushed to NuGet. The SpacetimeDB tag that they were built from is `v1.1.2-csharp-release`. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs None, because we're updating the DLLs to essentially include SpacetimeDB PRs. ## Testsuite SpacetimeDB branch name: master ## Testing CI I guess? Co-authored-by: Zeke Foppa --- .../{1.1.1.meta => 1.1.2.meta} | 0 .../{1.1.1 => 1.1.2}/analyzers.meta | 0 .../{1.1.1 => 1.1.2}/analyzers/dotnet.meta | 0 .../{1.1.1 => 1.1.2}/analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 74240 -> 74240 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.1.1 => 1.1.2}/lib.meta | 0 .../{1.1.1 => 1.1.2}/lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 68096 -> 68096 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1.meta => 1.1.2.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (86%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/lib/netstandard2.1.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll (97%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.1 => 1.1.2}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll similarity index 86% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 31f403008023be2f3db29361f66014ab193a8d53..dcb211fed93cc669e69b5608d21e4b520bc0a971 100755 GIT binary patch delta 4993 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 delta 5195 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 K@jc^219ku$>6~`} delta 485 zcmZpe!qPB>WkLr_Lv+fKi9Irmw&c?POW9+F+#T$=t4a{{bHqx?#45Bmzi8#2Xr3{oB**ECMt?C z?wWduQG4q@Mghj@3XF^@)A^Vf8#oymK#+lfar<;8MpGt6!|i8T7^4}34H>it<8 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta From 5baf66b628e1f256910c0beec4dddb1a532216ff Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Fri, 6 Jun 2025 11:07:24 -0700 Subject: [PATCH 215/223] Bump versions to 1.2.0 (#328) ## Description of Changes Bump versions to 1.2.0, as well as update the DLLs from SpacetimeDB (commit `fc8f7dcc8`). They don't have any changes, but the versions needed bumping. ## API This itself is not a breaking changes. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2837 ## Testsuite SpacetimeDB branch name: release/v1.2.0 ## Testing CI only --------- Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 6 +++--- sdks/csharp/package.json | 2 +- .../{1.1.2.meta => 1.2.0.meta} | 0 .../{1.1.2 => 1.2.0}/analyzers.meta | 0 .../{1.1.2 => 1.2.0}/analyzers/dotnet.meta | 0 .../{1.1.2 => 1.2.0}/analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 74240 -> 74240 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.1.2 => 1.2.0}/lib.meta | 0 .../{1.1.2 => 1.2.0}/lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 68096 -> 68096 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 12 files changed, 4 insertions(+), 4 deletions(-) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2.meta => 1.2.0.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (97%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/lib/netstandard2.1.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll (98%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.2 => 1.2.0}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index e43b40b8be7..b3ac109a6ad 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk - 1.1.5 - 1.1.5 + 1.2.0 + 1.2.0 $(DefaultItemExcludes);*~/** packages @@ -25,7 +25,7 @@ - + diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index bbf39864b3c..619551a053f 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.1.5", + "version": "1.2.0", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll similarity index 97% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index dcb211fed93cc669e69b5608d21e4b520bc0a971..0b21d31161215797ba068881e3707b008c556bd8 100755 GIT binary patch delta 329 zcmZoT!qRYrWkLr_@vB>>Hufx;#mvOOu-SNaVYI-(*(Ya2E%fl;$eFdYa}z87<}Kfv zr7eu~4D<{b7>pSi^bGZY9PPAZi!}3;jG`9gQU$1}9846X ze(IBZ{1zf#&+)bME#1CWobfgjKNABZ0|-Fr?bD?gGnrV881xtnwzJAIhBJnO*$mnY zX$;8>7C_RRAqB_+u?-kZ87vu$fovm&Bp@pZNT&hC%@`6HQh};WfNW!+dPA@(Q=sZp gAj=RaYdL+R9HTKO#AuLJf)b1(jN2I%82>W@02_Q;q5uE@ delta 329 zcmZoT!qRYrWkLrFzvje-jXg_dF*7nSZ8n}=7%gzl>Osm&wlJ?b@$G^)TY_6RZ~4|N zZDFWqq-VguV9dy%X9$Ew+NsG#W@)BIW~nJ@MkdLoM&>C=X+{R-$%f`Yfi&YpAltyg zGG%+d5Thsy3)j-u3#NC7F$M_46rWihoBZE_)aC(_e@&E>(bvO4mb0f$9~k zWFM{F(th*kz2!`&wyzauyv@YV$iT?Jz`z6~!Swd&QjD2QtcDDF3`W~oWf{X6L&0nY zZH82aWCkM!GlnzWkLswTv+P#jXksWF*7kRY}VXgt|n0W-s;B+{g)n_BCc}(yL0E@<_%Bx ziCP%x8R!`>Fc>p3=o#t(IofH-7HQ@w$;lQ5rk2LZMoE@QMrjsiiK!_j7RKg=md2*0 zsg{O`mYbLTzQxSqwVLDj|D_60!Kp4#L7-~) zKaaOPo)=JK)^?Zq#@3aL_Zj(_7#JBq07`G4&ctZQ#A?K#$6&DiEDK{eVWkLtbkE|6BH}=fh$IQsUv{`e1xthT24O45U7uou53w`2hw(PR@<_%Bx ziCP%y8R;1?Fc>p3=otc`k#=gbky)Clky&a=nvqGesgZd~Qks#0d9tB7P$11X5y&>M zuuR#!?Ds8Zmcvq88z;B?4-hbp(NyBwaMX3@ek1wjXC8khKl#5@0V>$~6DkN)&Dj0x zMHfek-nYdb40>BvGTvw8XJlYxU|?VZl3;rKbS6eaCRRfRJqDxgXIU7-8AHKr25p8^ zhGYgK1~Y~<22(Jd%8&wN8!?yw#X%zGKzn SL(23@Hb!HpH5=I&{h0xC&RUTG diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta From 544085caf030fe583f16e20acce1b39c8ab9cb7b Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Fri, 6 Jun 2025 15:28:17 -0300 Subject: [PATCH 216/223] Example of custom event handling (#327) ## Description of Changes *Describe what has been changed, any new features or bug fixes* ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] Describe a test for this PR that you have completed --------- Co-authored-by: Alessandro Asoni Co-authored-by: James Gilles --- sdks/csharp/src/EventHandling.meta | 8 ++ .../src/EventHandling/AbstractEventHandler.cs | 100 ++++++++++++++++++ .../AbstractEventHandler.cs.meta | 11 ++ .../src/EventHandling/EventListeners.cs | 40 +++++++ .../src/EventHandling/EventListeners.cs.meta | 11 ++ .../src/EventHandling/ListExtensions.cs | 27 +++++ .../src/EventHandling/ListExtensions.cs.meta | 11 ++ sdks/csharp/src/Table.cs | 92 +++++++++++++--- 8 files changed, 285 insertions(+), 15 deletions(-) create mode 100644 sdks/csharp/src/EventHandling.meta create mode 100644 sdks/csharp/src/EventHandling/AbstractEventHandler.cs create mode 100644 sdks/csharp/src/EventHandling/AbstractEventHandler.cs.meta create mode 100644 sdks/csharp/src/EventHandling/EventListeners.cs create mode 100644 sdks/csharp/src/EventHandling/EventListeners.cs.meta create mode 100644 sdks/csharp/src/EventHandling/ListExtensions.cs create mode 100644 sdks/csharp/src/EventHandling/ListExtensions.cs.meta diff --git a/sdks/csharp/src/EventHandling.meta b/sdks/csharp/src/EventHandling.meta new file mode 100644 index 00000000000..dc3e6f008a7 --- /dev/null +++ b/sdks/csharp/src/EventHandling.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5b0a1c7040cb63047b7229b408a9604b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/EventHandling/AbstractEventHandler.cs b/sdks/csharp/src/EventHandling/AbstractEventHandler.cs new file mode 100644 index 00000000000..1d6e03b4ada --- /dev/null +++ b/sdks/csharp/src/EventHandling/AbstractEventHandler.cs @@ -0,0 +1,100 @@ +using System; + +namespace SpacetimeDB.EventHandling +{ + internal class AbstractEventHandler + { + private EventListeners Listeners { get; } = new(); + + public void Invoke() + { + for (var i = Listeners.Count - 1; i >= 0; i--) + { + Listeners[i]?.Invoke(); + } + } + + public void AddListener(Action listener) => Listeners.Add(listener); + + public void RemoveListener(Action listener) => Listeners.Remove(listener); + } + internal class AbstractEventHandler + { + private EventListeners> Listeners { get; } = new(); + + public void Invoke(T value) + { + for (var i = Listeners.Count - 1; i >= 0; i--) + { + Listeners[i]?.Invoke(value); + } + } + + public void AddListener(Action listener) => Listeners.Add(listener); + public void RemoveListener(Action listener) => Listeners.Remove(listener); + } + + internal class AbstractEventHandler + { + private EventListeners> Listeners { get; } = new(); + + public void Invoke(T1 v1, T2 v2) + { + for (var i = Listeners.Count - 1; i >= 0; i--) + { + Listeners[i]?.Invoke(v1, v2); + } + } + + public void AddListener(Action listener) => Listeners.Add(listener); + public void RemoveListener(Action listener) => Listeners.Remove(listener); + } + + internal class AbstractEventHandler + { + private EventListeners> Listeners { get; } = new(); + + public void Invoke(T1 v1, T2 v2, T3 v3) + { + for (var i = Listeners.Count - 1; i >= 0; i--) + { + Listeners[i]?.Invoke(v1, v2, v3); + } + } + + public void AddListener(Action listener) => Listeners.Add(listener); + public void RemoveListener(Action listener) => Listeners.Remove(listener); + } + + internal class AbstractEventHandler + { + private EventListeners> Listeners { get; } = new(); + + public void Invoke(T1 v1, T2 v2, T3 v3, T4 v4) + { + for (var i = Listeners.Count - 1; i >= 0; i--) + { + Listeners[i]?.Invoke(v1, v2, v3, v4); + } + } + + public void AddListener(Action listener) => Listeners.Add(listener); + public void RemoveListener(Action listener) => Listeners.Remove(listener); + } + + internal class AbstractEventHandler + { + private EventListeners> Listeners { get; } = new(); + + public void Invoke(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) + { + for (var i = Listeners.Count - 1; i >= 0; i--) + { + Listeners[i]?.Invoke(v1, v2, v3, v4, v5); + } + } + + public void AddListener(Action listener) => Listeners.Add(listener); + public void RemoveListener(Action listener) => Listeners.Remove(listener); + } +} \ No newline at end of file diff --git a/sdks/csharp/src/EventHandling/AbstractEventHandler.cs.meta b/sdks/csharp/src/EventHandling/AbstractEventHandler.cs.meta new file mode 100644 index 00000000000..2ceef79f6e5 --- /dev/null +++ b/sdks/csharp/src/EventHandling/AbstractEventHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3ff844e9ff394788a1bc7e8e83ac86b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/EventHandling/EventListeners.cs b/sdks/csharp/src/EventHandling/EventListeners.cs new file mode 100644 index 00000000000..d4acc4b7218 --- /dev/null +++ b/sdks/csharp/src/EventHandling/EventListeners.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; + +namespace SpacetimeDB.EventHandling +{ + internal class EventListeners where T : Delegate + { + private List List { get; } + private Dictionary Indices { get; } + + public int Count => List.Count; + + public T this[int index] => List[index]; + + public EventListeners() : this(0) { } + public EventListeners(int initialSize) + { + List = new List(initialSize); + Indices = new Dictionary(initialSize); + } + + public void Add(T listener) + { + if (listener == null || !Indices.TryAdd(listener, List.Count)) return; + List.Add(listener); + } + + public void Remove(T listener) + { + if (listener == null || List.Count <= 0 || !Indices.Remove(listener, out var index)) return; + var lastListener = List[^1]; + if (lastListener != listener) + { + Indices[lastListener] = index; + } + + List.RemoveAtSwapBack(index); + } + } +} \ No newline at end of file diff --git a/sdks/csharp/src/EventHandling/EventListeners.cs.meta b/sdks/csharp/src/EventHandling/EventListeners.cs.meta new file mode 100644 index 00000000000..f234301ba71 --- /dev/null +++ b/sdks/csharp/src/EventHandling/EventListeners.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 995f02ea579fa442a9fef6f44b275c65 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/EventHandling/ListExtensions.cs b/sdks/csharp/src/EventHandling/ListExtensions.cs new file mode 100644 index 00000000000..652ee0551f8 --- /dev/null +++ b/sdks/csharp/src/EventHandling/ListExtensions.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace SpacetimeDB.EventHandling +{ + internal static class ListExtensions + { + public static void RemoveAtSwapBack(this List list, int index) + { + if (list == null) throw new ArgumentNullException(nameof(list)); + + var lastIndex = list.Count - 1; + + if (index < 0 || index > lastIndex) throw new ArgumentOutOfRangeException(nameof(index), "Index is out of range."); + + if (index == lastIndex) + { + list.RemoveAt(index); + return; + } + + list[index] = list[lastIndex]; + + list.RemoveAt(lastIndex); + } + } +} \ No newline at end of file diff --git a/sdks/csharp/src/EventHandling/ListExtensions.cs.meta b/sdks/csharp/src/EventHandling/ListExtensions.cs.meta new file mode 100644 index 00000000000..4acfdff5bd0 --- /dev/null +++ b/sdks/csharp/src/EventHandling/ListExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c6c0d14218754193902cbb2dbf666da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index 1394f10d83f..4f90cf8276f 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using SpacetimeDB.BSATN; using SpacetimeDB.ClientApi; +using SpacetimeDB.EventHandling; #nullable enable namespace SpacetimeDB @@ -134,8 +135,18 @@ public RemoteTableHandle(IDbConnection conn) : base(conn) { } // I didn't do that because that delays the index updates until after the row is processed. // In theory, that shouldn't be the issue, but I didn't want to break it right before leaving :) // - Ingvar - private event Action? OnInternalInsert; - private event Action? OnInternalDelete; + private AbstractEventHandler OnInternalInsertHandler { get; } = new(); + private event Action OnInternalInsert + { + add => OnInternalInsertHandler.AddListener(value); + remove => OnInternalInsertHandler.RemoveListener(value); + } + private AbstractEventHandler OnInternalDeleteHandler { get; } = new(); + private event Action OnInternalDelete + { + add => OnInternalDeleteHandler.AddListener(value); + remove => OnInternalDeleteHandler.RemoveListener(value); + } // These are implementations of the type-erased interface. object? IRemoteTableHandle.GetPrimaryKey(IStructuralReadWrite row) => GetPrimaryKey((Row)row); @@ -177,12 +188,32 @@ private static IReadWrite Serializer IStructuralReadWrite IRemoteTableHandle.DecodeValue(BinaryReader reader) => Serializer.Read(reader); public delegate void RowEventHandler(EventContext context, Row row); - public event RowEventHandler? OnInsert; - public event RowEventHandler? OnDelete; - public event RowEventHandler? OnBeforeDelete; + private CustomRowEventHandler OnInsertHandler { get; } = new(); + public event RowEventHandler OnInsert + { + add => OnInsertHandler.AddListener(value); + remove => OnInsertHandler.RemoveListener(value); + } + private CustomRowEventHandler OnDeleteHandler { get; } = new(); + public event RowEventHandler OnDelete + { + add => OnDeleteHandler.AddListener(value); + remove => OnDeleteHandler.RemoveListener(value); + } + private CustomRowEventHandler OnBeforeDeleteHandler { get; } = new(); + public event RowEventHandler OnBeforeDelete + { + add => OnBeforeDeleteHandler.AddListener(value); + remove => OnBeforeDeleteHandler.RemoveListener(value); + } public delegate void UpdateEventHandler(EventContext context, Row oldRow, Row newRow); - public event UpdateEventHandler? OnUpdate; + private CustomUpdateEventHandler OnUpdateHandler { get; } = new(); + public event UpdateEventHandler OnUpdate + { + add => OnUpdateHandler.AddListener(value); + remove => OnUpdateHandler.RemoveListener(value); + } public int Count => (int)Entries.CountDistinct; @@ -195,7 +226,7 @@ void InvokeInsert(IEventContext context, IStructuralReadWrite row) { try { - OnInsert?.Invoke((EventContext)context, (Row)row); + OnInsertHandler.Invoke((EventContext)context, (Row)row); } catch (Exception e) { @@ -207,7 +238,7 @@ void InvokeDelete(IEventContext context, IStructuralReadWrite row) { try { - OnDelete?.Invoke((EventContext)context, (Row)row); + OnDeleteHandler.Invoke((EventContext)context, (Row)row); } catch (Exception e) { @@ -219,7 +250,7 @@ void InvokeBeforeDelete(IEventContext context, IStructuralReadWrite row) { try { - OnBeforeDelete?.Invoke((EventContext)context, (Row)row); + OnBeforeDeleteHandler.Invoke((EventContext)context, (Row)row); } catch (Exception e) { @@ -231,7 +262,7 @@ void InvokeUpdate(IEventContext context, IStructuralReadWrite oldRow, IStructura { try { - OnUpdate?.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); + OnUpdateHandler.Invoke((EventContext)context, (Row)oldRow, (Row)newRow); } catch (Exception e) { @@ -276,7 +307,7 @@ void IRemoteTableHandle.Apply(IEventContext context, MultiDictionaryDelta Listeners { get; } = new(); + + public void Invoke(EventContext ctx, Row row) + { + for (var i = Listeners.Count - 1; i >= 0; i--) + { + Listeners[i]?.Invoke(ctx, row); + } + } + + public void AddListener(RowEventHandler listener) => Listeners.Add(listener); + public void RemoveListener(RowEventHandler listener) => Listeners.Remove(listener); + } + private class CustomUpdateEventHandler + { + private EventListeners Listeners { get; } = new(); + + public void Invoke(EventContext ctx, Row oldRow, Row newRow) + { + for (var i = Listeners.Count - 1; i >= 0; i--) + { + Listeners[i]?.Invoke(ctx, oldRow, newRow); + } + } + + public void AddListener(UpdateEventHandler listener) => Listeners.Add(listener); + public void RemoveListener(UpdateEventHandler listener) => Listeners.Remove(listener); + } } } -#nullable disable +#nullable disable \ No newline at end of file From e3b392ad810be151f16cdb74b94d41ed1b786b27 Mon Sep 17 00:00:00 2001 From: james gilles Date: Fri, 6 Jun 2025 17:02:30 -0400 Subject: [PATCH 217/223] Faster Stats.cs (#326) ## Description of Changes `NetworkRequestTracker` previously was keeping all historical reducer request data, and searching through this every frame to get statistics. I've modified it to throw out much more data -- it's much faster now, but only updates every few seconds. ## API Not an API break, but deprecates an argument of one of NetworkRequestTracker's methods to no longer do anything. Adds new APIs. ## Requires SpacetimeDB PRs N/A ## Testsuite SpacetimeDB branch name: master ## Testing - [x] Tested Bitcraft. **Their F9 debug menu will require an update, since we now only keep one time window of request data, rather than being able to give information about multiple windows.** But it works. - [x] Blackholio CI --- sdks/csharp/src/Stats.cs | 188 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 174 insertions(+), 14 deletions(-) diff --git a/sdks/csharp/src/Stats.cs b/sdks/csharp/src/Stats.cs index bac011d0b82..3323422c32b 100644 --- a/sdks/csharp/src/Stats.cs +++ b/sdks/csharp/src/Stats.cs @@ -1,25 +1,144 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; namespace SpacetimeDB { + /// + /// Class to track information about network requests and other internal statistics. + /// public class NetworkRequestTracker { - private readonly ConcurrentQueue<(DateTime End, TimeSpan Duration, string Metadata)> _requestDurations = new(); + public NetworkRequestTracker() + { + } + + /// + /// The fastest request OF ALL TIME. + /// We keep data for less time than we used to -- having this around catches outliers that may be problematic. + /// + public (TimeSpan Duration, string Metadata)? AllTimeMin + { + get; private set; + } + + /// + /// The slowest request OF ALL TIME. + /// We keep data for less time than we used to -- having this around catches outliers that may be problematic. + /// + public (TimeSpan Duration, string Metadata)? AllTimeMax + { + get; private set; + } + + private int _totalSamples = 0; + + /// + /// The maximum number of windows we are willing to track data in. + /// + public static readonly int MAX_TRACKERS = 16; + + /// + /// A tracker that tracks the minimum and maximum sample in a time window, + /// resetting after windowSeconds seconds. + /// + private struct Tracker + { + public Tracker(int windowSeconds) + { + LastReset = DateTime.UtcNow; + Window = new TimeSpan(0, 0, windowSeconds); + LastWindowMin = null; + LastWindowMax = null; + ThisWindowMin = null; + ThisWindowMax = null; + } + + private DateTime LastReset; + private TimeSpan Window; + + // The min and max for the previous window. + private (TimeSpan Duration, string Metadata)? LastWindowMin; + private (TimeSpan Duration, string Metadata)? LastWindowMax; + + // The min and max for the current window. + private (TimeSpan Duration, string Metadata)? ThisWindowMin; + private (TimeSpan Duration, string Metadata)? ThisWindowMax; + + public void InsertRequest(TimeSpan duration, string metadata) + { + var sample = (duration, metadata); + + if (ThisWindowMin == null || ThisWindowMin.Value.Duration > duration) + { + ThisWindowMin = sample; + } + if (ThisWindowMax == null || ThisWindowMax.Value.Duration < duration) + { + ThisWindowMax = sample; + } + + if (LastReset < DateTime.UtcNow - Window) + { + LastReset = DateTime.UtcNow; + LastWindowMax = ThisWindowMax; + LastWindowMin = ThisWindowMin; + ThisWindowMax = null; + ThisWindowMin = null; + } + } + + public ((TimeSpan Duration, string Metadata) Min, (TimeSpan Duration, string Metadata) Max)? GetMinMaxTimes() + { + if (LastWindowMin != null && LastWindowMax != null) + { + return (LastWindowMin.Value, LastWindowMax.Value); + } + + return null; + } + } + + /// + /// Maps (requested window time in seconds) -> (the tracker for that time window). + /// + private readonly Dictionary Trackers = new(); + /// + /// To allow modifying Trackers in a loop. + /// This is needed because we made Tracker a struct. + /// + private readonly HashSet TrackerWindows = new(); + + /// + /// ID for the next in-flight request. + /// private uint _nextRequestId; + + /// + /// In-flight requests that have not yet finished running. + /// private readonly Dictionary _requests = new(); internal uint StartTrackingRequest(string metadata = "") { - // Record the start time of the request - var newRequestId = ++_nextRequestId; - _requests[newRequestId] = (DateTime.UtcNow, metadata); - return newRequestId; + // This method is called when the user submits a new request. + // It's possible the user was naughty and did this off the main thread. + // So, be a little paranoid and lock ourselves. Uncontended this will be pretty fast. + lock (this) + { + // Get a new request ID. + // Note: C# wraps by default, rather than throwing exception on overflow. + // So, this class should work forever. + var newRequestId = ++_nextRequestId; + // Record the start time of the request. + _requests[newRequestId] = (DateTime.UtcNow, metadata); + return newRequestId; + } } + // The remaining methods in this class do not need to lock, since they are only called from OnProcessMessageComplete. + internal bool FinishTrackingRequest(uint requestId) { if (!_requests.Remove(requestId, out var entry)) @@ -42,7 +161,24 @@ internal bool FinishTrackingRequest(uint requestId) internal void InsertRequest(TimeSpan duration, string metadata) { - _requestDurations.Enqueue((DateTime.UtcNow, duration, metadata)); + var sample = (duration, metadata); + + if (AllTimeMin == null || AllTimeMin.Value.Duration > duration) + { + AllTimeMin = sample; + } + if (AllTimeMax == null || AllTimeMax.Value.Duration < duration) + { + AllTimeMax = sample; + } + _totalSamples += 1; + + foreach (var window in TrackerWindows) + { + var tracker = Trackers[window]; + tracker.InsertRequest(duration, metadata); + Trackers[window] = tracker; // Needed because struct. + } } internal void InsertRequest(DateTime start, string metadata) @@ -50,20 +186,44 @@ internal void InsertRequest(DateTime start, string metadata) InsertRequest(DateTime.UtcNow - start, metadata); } - public ((TimeSpan Duration, string Metadata) Min, (TimeSpan Duration, string Metadata) Max)? GetMinMaxTimes(int lastSeconds) + /// + /// Get the the minimum- and maximum-duration events in lastSeconds. + /// When first called, this will return null until `lastSeconds` have passed. + /// After this, the value will update every `lastSeconds`. + /// + /// This class allocates an internal data structure for every distinct value of `lastSeconds` passed. + /// After `NetworkRequestTracker.MAX_TRACKERS` distinct values have been passed, it will stop allocating internal data structures + /// and always return null. + /// This should be fine as long as you don't request a large number of distinct windows. + /// + /// Present for backwards-compatibility, does nothing. + public ((TimeSpan Duration, string Metadata) Min, (TimeSpan Duration, string Metadata) Max)? GetMinMaxTimes(int lastSeconds = 0) { - var cutoff = DateTime.UtcNow.AddSeconds(-lastSeconds); - var requestDurations = _requestDurations.Where(x => x.End >= cutoff).Select(x => (x.Duration, x.Metadata)); + if (lastSeconds <= 0) return null; - if (!requestDurations.Any()) + if (Trackers.TryGetValue(lastSeconds, out var tracker)) { - return null; + return tracker.GetMinMaxTimes(); + } + else if (TrackerWindows.Count < MAX_TRACKERS) + { + TrackerWindows.Add(lastSeconds); + Trackers.Add(lastSeconds, new Tracker(lastSeconds)); } - return (requestDurations.Min(), requestDurations.Max()); + return null; } - public int GetSampleCount() => _requestDurations.Count; + /// + /// Get the number of samples in the window. + /// + /// + public int GetSampleCount() => _totalSamples; + + /// + /// Get the number of outstanding tracked requests. + /// + /// public int GetRequestsAwaitingResponse() => _requests.Count; } From e168ec6f9002610c0c39536d2e12e95df607b71e Mon Sep 17 00:00:00 2001 From: james gilles Date: Wed, 18 Jun 2025 13:37:52 -0400 Subject: [PATCH 218/223] More granular request process tracking (#330) ## Description of Changes Addresses https://github.com/clockworklabs/SpacetimeDBPrivate/issues/1786 and https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/329. Marks messages as parsed from the background parsing thread, and then marks them as applied using a separate tracker once they are applied. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing - [x] Testing against Bitcraft --- sdks/csharp/src/SpacetimeDBClient.cs | 234 ++++++++++-------- sdks/csharp/src/Stats.cs | 156 ++++++++---- ...p_dumpName=LegacySubscribeAll.verified.txt | 13 +- ...ump_dumpName=SubscribeApplied.verified.txt | 13 +- sdks/csharp/tests~/SnapshotTests.cs | 2 +- 5 files changed, 271 insertions(+), 147 deletions(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 3f83e6969c9..c19f05b2ed4 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -127,7 +127,6 @@ public abstract class DbConnectionBase : IDbConne { public static DbConnectionBuilder Builder() => new(); - internal event Action? onConnect; /// @@ -168,7 +167,7 @@ public abstract class DbConnectionBase : IDbConne private readonly Dictionary> waitingOneOffQueries = new(); private bool isClosing; - private readonly Thread networkMessageProcessThread; + private readonly Thread networkMessageParseThread; public readonly Stats stats = new(); protected DbConnectionBase() @@ -193,24 +192,36 @@ protected DbConnectionBase() #if UNITY_WEBGL && !UNITY_EDITOR if (SpacetimeDBNetworkManager._instance != null) - SpacetimeDBNetworkManager._instance.StartCoroutine(PreProcessMessages()); + SpacetimeDBNetworkManager._instance.StartCoroutine(ParseMessages()); #endif #endif #if !(UNITY_WEBGL && !UNITY_EDITOR) - // For targets other than webgl we start a thread to pre-process messages - networkMessageProcessThread = new Thread(PreProcessMessages); - networkMessageProcessThread.Start(); + // For targets other than webgl we start a thread to parse messages + networkMessageParseThread = new Thread(ParseMessages); + networkMessageParseThread.Start(); #endif } - struct UnprocessedMessage + internal struct UnparsedMessage { + /// + /// The bytes of the message. + /// public byte[] bytes; + + /// + /// The timestamp the message came off the wire. + /// public DateTime timestamp; + + /// + /// The ID assigned by the message parsing queue tracker. + /// + public uint parseQueueTrackerId; } - struct ProcessedDatabaseUpdate + internal struct ParsedDatabaseUpdate { // Map: table handles -> (primary key -> IStructuralReadWrite). // If a particular table has no primary key, the "primary key" is just the row itself. @@ -218,9 +229,9 @@ struct ProcessedDatabaseUpdate public Dictionary> Updates; // Can't override the default constructor. Make sure you use this one! - public static ProcessedDatabaseUpdate New() + public static ParsedDatabaseUpdate New() { - ProcessedDatabaseUpdate result; + ParsedDatabaseUpdate result; result.Updates = new(); return result; } @@ -237,25 +248,26 @@ public MultiDictionaryDelta DeltaForTable(IRemoteT } } - struct ProcessedMessage + internal struct ParsedMessage { public ServerMessage message; - public ProcessedDatabaseUpdate dbOps; - public DateTime timestamp; + public ParsedDatabaseUpdate dbOps; + public DateTime receiveTimestamp; + public uint applyQueueTrackerId; public ReducerEvent? reducerEvent; } - private readonly BlockingCollection _messageQueue = - new(new ConcurrentQueue()); + private readonly BlockingCollection _parseQueue = + new(new ConcurrentQueue()); - private readonly BlockingCollection _preProcessedNetworkMessages = - new(new ConcurrentQueue()); + private readonly BlockingCollection _applyQueue = + new(new ConcurrentQueue()); internal static bool IsTesting; - internal bool HasPreProcessedMessage => _preProcessedNetworkMessages.Count > 0; + internal bool HasMessageToApply => _applyQueue.Count > 0; - private readonly CancellationTokenSource _preProcessCancellationTokenSource = new(); - private CancellationToken _preProcessCancellationToken => _preProcessCancellationTokenSource.Token; + private readonly CancellationTokenSource _parseCancellationTokenSource = new(); + private CancellationToken _parseCancellationToken => _parseCancellationTokenSource.Token; /// /// Decode a row for a table, producing a primary key. @@ -266,7 +278,7 @@ struct ProcessedMessage /// /// /// - static IStructuralReadWrite Decode(IRemoteTableHandle table, BinaryReader reader, out object primaryKey) + internal static IStructuralReadWrite Decode(IRemoteTableHandle table, BinaryReader reader, out object primaryKey) { var obj = table.DecodeValue(reader); @@ -282,7 +294,7 @@ static IStructuralReadWrite Decode(IRemoteTableHandle table, BinaryReader reader private static readonly Status Committed = new Status.Committed(default); private static readonly Status OutOfEnergy = new Status.OutOfEnergy(default); - enum CompressionAlgos : byte + internal enum CompressionAlgos : byte { None = 0, Brotli = 1, @@ -387,10 +399,21 @@ private static (BinaryReader reader, int rowCount) ParseRowList(BsatnRowList lis } ); + /// + /// Get a description of a message suitable for storing in the tracker metadata. + /// + /// + /// + internal string TrackerMetadataForMessage(ServerMessage message) => message switch + { + ServerMessage.TransactionUpdate(var transactionUpdate) => $"type={nameof(ServerMessage.TransactionUpdate)},reducer={transactionUpdate.ReducerCall.ReducerName}", + _ => $"type={message.GetType().Name}" + }; + #if UNITY_WEBGL && !UNITY_EDITOR - IEnumerator PreProcessMessages() + internal IEnumerator ParseMessages() #else - void PreProcessMessages() + internal void ParseMessages() #endif { while (!isClosing) @@ -402,9 +425,9 @@ void PreProcessMessages() #endif try { - var message = _messageQueue.Take(_preProcessCancellationToken); - var preprocessedMessage = PreProcessMessage(message); - _preProcessedNetworkMessages.Add(preprocessedMessage, _preProcessCancellationToken); + var message = _parseQueue.Take(_parseCancellationToken); + var parsedMessage = ParseMessage(message); + _applyQueue.Add(parsedMessage, _parseCancellationToken); } catch (OperationCanceledException) { @@ -431,16 +454,16 @@ void PreProcessMessages() } } - ProcessedDatabaseUpdate PreProcessLegacySubscription(InitialSubscription initSub) + ParsedDatabaseUpdate ParseLegacySubscription(InitialSubscription initSub) { - var dbOps = ProcessedDatabaseUpdate.New(); + var dbOps = ParsedDatabaseUpdate.New(); // This is all of the inserts int cap = initSub.DatabaseUpdate.Tables.Sum(a => (int)a.NumRows); // First apply all of the state foreach (var (table, update) in GetTables(initSub.DatabaseUpdate)) { - PreProcessInsertOnlyTable(table, update, dbOps); + ParseInsertOnlyTable(table, update, dbOps); } return dbOps; } @@ -449,17 +472,17 @@ ProcessedDatabaseUpdate PreProcessLegacySubscription(InitialSubscription initSub /// TODO: the dictionary is here for backwards compatibility and can be removed /// once we get rid of legacy subscriptions. /// - ProcessedDatabaseUpdate PreProcessSubscribeMultiApplied(SubscribeMultiApplied subscribeMultiApplied) + ParsedDatabaseUpdate ParseSubscribeMultiApplied(SubscribeMultiApplied subscribeMultiApplied) { - var dbOps = ProcessedDatabaseUpdate.New(); + var dbOps = ParsedDatabaseUpdate.New(); foreach (var (table, update) in GetTables(subscribeMultiApplied.Update)) { - PreProcessInsertOnlyTable(table, update, dbOps); + ParseInsertOnlyTable(table, update, dbOps); } return dbOps; } - void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, ProcessedDatabaseUpdate dbOps) + void ParseInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, ParsedDatabaseUpdate dbOps) { var delta = dbOps.DeltaForTable(table); @@ -479,7 +502,7 @@ void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, Pro } } - void PreProcessDeleteOnlyTable(IRemoteTableHandle table, TableUpdate update, ProcessedDatabaseUpdate dbOps) + void ParseDeleteOnlyTable(IRemoteTableHandle table, TableUpdate update, ParsedDatabaseUpdate dbOps) { var delta = dbOps.DeltaForTable(table); foreach (var cqu in update.Updates) @@ -499,7 +522,7 @@ void PreProcessDeleteOnlyTable(IRemoteTableHandle table, TableUpdate update, Pro } } - void PreProcessTable(IRemoteTableHandle table, TableUpdate update, ProcessedDatabaseUpdate dbOps) + void ParseTable(IRemoteTableHandle table, TableUpdate update, ParsedDatabaseUpdate dbOps) { var delta = dbOps.DeltaForTable(table); foreach (var cqu in update.Updates) @@ -526,30 +549,30 @@ void PreProcessTable(IRemoteTableHandle table, TableUpdate update, ProcessedData } - ProcessedDatabaseUpdate PreProcessUnsubscribeMultiApplied(UnsubscribeMultiApplied unsubMultiApplied) + ParsedDatabaseUpdate ParseUnsubscribeMultiApplied(UnsubscribeMultiApplied unsubMultiApplied) { - var dbOps = ProcessedDatabaseUpdate.New(); + var dbOps = ParsedDatabaseUpdate.New(); foreach (var (table, update) in GetTables(unsubMultiApplied.Update)) { - PreProcessDeleteOnlyTable(table, update, dbOps); + ParseDeleteOnlyTable(table, update, dbOps); } return dbOps; } - ProcessedDatabaseUpdate PreProcessDatabaseUpdate(DatabaseUpdate updates) + ParsedDatabaseUpdate ParseDatabaseUpdate(DatabaseUpdate updates) { - var dbOps = ProcessedDatabaseUpdate.New(); + var dbOps = ParsedDatabaseUpdate.New(); foreach (var (table, update) in GetTables(updates)) { - PreProcessTable(table, update, dbOps); + ParseTable(table, update, dbOps); } return dbOps; } - void PreProcessOneOffQuery(OneOffQueryResponse resp) + void ParseOneOffQuery(OneOffQueryResponse resp) { /// This case does NOT produce a list of DBOps, because it should not modify the client cache state! var messageId = new Guid(resp.MessageId.ToArray()); @@ -563,35 +586,48 @@ void PreProcessOneOffQuery(OneOffQueryResponse resp) resultSource.SetResult(resp); } - ProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) + ParsedMessage ParseMessage(UnparsedMessage unparsed) { - var dbOps = ProcessedDatabaseUpdate.New(); + var dbOps = ParsedDatabaseUpdate.New(); + var message = DecompressDecodeMessage(unparsed.bytes); + var trackerMetadata = TrackerMetadataForMessage(message); - var message = DecompressDecodeMessage(unprocessed.bytes); + stats.ParseMessageQueueTracker.FinishTrackingRequest(unparsed.parseQueueTrackerId, trackerMetadata); + var parseStart = DateTime.UtcNow; ReducerEvent? reducerEvent = default; switch (message) { case ServerMessage.InitialSubscription(var initSub): - dbOps = PreProcessLegacySubscription(initSub); + stats.SubscriptionRequestTracker.FinishTrackingRequest(initSub.RequestId, unparsed.timestamp); + dbOps = ParseLegacySubscription(initSub); break; case ServerMessage.SubscribeApplied(var subscribeApplied): break; case ServerMessage.SubscribeMultiApplied(var subscribeMultiApplied): - dbOps = PreProcessSubscribeMultiApplied(subscribeMultiApplied); + stats.SubscriptionRequestTracker.FinishTrackingRequest(subscribeMultiApplied.RequestId, unparsed.timestamp); + dbOps = ParseSubscribeMultiApplied(subscribeMultiApplied); break; case ServerMessage.SubscriptionError(var subscriptionError): // do nothing; main thread will warn. + if (subscriptionError.RequestId.HasValue) + { + stats.SubscriptionRequestTracker.FinishTrackingRequest(subscriptionError.RequestId.Value, unparsed.timestamp); + } break; case ServerMessage.UnsubscribeApplied(var unsubscribeApplied): // do nothing; main thread will warn. break; case ServerMessage.UnsubscribeMultiApplied(var unsubscribeMultiApplied): - dbOps = PreProcessUnsubscribeMultiApplied(unsubscribeMultiApplied); + stats.SubscriptionRequestTracker.FinishTrackingRequest(unsubscribeMultiApplied.RequestId, unparsed.timestamp); + dbOps = ParseUnsubscribeMultiApplied(unsubscribeMultiApplied); break; case ServerMessage.TransactionUpdate(var transactionUpdate): // Convert the generic event arguments in to a domain specific event object + var hostDuration = (TimeSpan)transactionUpdate.TotalHostExecutionDuration; + stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={transactionUpdate.ReducerCall.ReducerName}"); + try { reducerEvent = new( @@ -612,28 +648,46 @@ ProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) { // Failing to parse the ReducerEvent is fine, it just means we should // call downstream stuff with an UnknownTransaction. - // See OnProcessMessageComplete. + // See ApplyMessage + } + + var callerIdentity = transactionUpdate.CallerIdentity; + if (callerIdentity == Identity && transactionUpdate.CallerConnectionId == ConnectionId) + { + // This was a request that we initiated + var requestId = transactionUpdate.ReducerCall.RequestId; + // Make sure we mark the request as having finished when it came off the wire. + // That's why we use unparsed.timestamp, rather than DateTime.UtcNow. + // See ReducerRequestTracker's comment. + if (!stats.ReducerRequestTracker.FinishTrackingRequest(requestId, unparsed.timestamp)) + { + Log.Warn($"Failed to finish tracking reducer request: {requestId}"); + } } if (transactionUpdate.Status is UpdateStatus.Committed(var committed)) { - dbOps = PreProcessDatabaseUpdate(committed); + dbOps = ParseDatabaseUpdate(committed); } + break; case ServerMessage.TransactionUpdateLight(var update): - dbOps = PreProcessDatabaseUpdate(update.Update); + dbOps = ParseDatabaseUpdate(update.Update); break; case ServerMessage.IdentityToken(var identityToken): break; case ServerMessage.OneOffQueryResponse(var resp): - PreProcessOneOffQuery(resp); + ParseOneOffQuery(resp); break; default: throw new InvalidOperationException(); } - return new ProcessedMessage { message = message, dbOps = dbOps, timestamp = unprocessed.timestamp, reducerEvent = reducerEvent }; + stats.ParseMessageTracker.InsertRequest(parseStart, trackerMetadata); + var applyTracker = stats.ApplyMessageQueueTracker.StartTrackingRequest(trackerMetadata); + + return new ParsedMessage { message = message, dbOps = dbOps, receiveTimestamp = unparsed.timestamp, applyQueueTrackerId = applyTracker, reducerEvent = reducerEvent }; } } @@ -648,7 +702,7 @@ public void Disconnect() webSocket.Close(); } - _preProcessCancellationTokenSource.Cancel(); + _parseCancellationTokenSource.Cancel(); } /// @@ -703,7 +757,7 @@ async Task Function() } - private void OnMessageProcessCompleteUpdate(IEventContext eventContext, ProcessedDatabaseUpdate dbOps) + private void ApplyUpdate(IEventContext eventContext, ParsedDatabaseUpdate dbOps) { // First trigger OnBeforeDelete foreach (var (table, update) in dbOps.Updates) @@ -724,21 +778,22 @@ private void OnMessageProcessCompleteUpdate(IEventContext eventContext, Processe protected abstract bool Dispatch(IReducerEventContext context, Reducer reducer); - private void OnMessageProcessComplete(ProcessedMessage processed) + private void ApplyMessage(ParsedMessage parsed) { - var message = processed.message; - var dbOps = processed.dbOps; - var timestamp = processed.timestamp; + var message = parsed.message; + var dbOps = parsed.dbOps; + var timestamp = parsed.receiveTimestamp; + + stats.ApplyMessageQueueTracker.FinishTrackingRequest(parsed.applyQueueTrackerId); + var applyStart = DateTime.UtcNow; switch (message) { case ServerMessage.InitialSubscription(var initialSubscription): { - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.InitialSubscription)}"); - stats.SubscriptionRequestTracker.FinishTrackingRequest(initialSubscription.RequestId); var eventContext = MakeSubscriptionEventContext(); var legacyEventContext = ToEventContext(new Event.SubscribeApplied()); - OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); + ApplyUpdate(legacyEventContext, dbOps); if (legacySubscriptions.TryGetValue(initialSubscription.RequestId, out var subscription)) { @@ -760,11 +815,9 @@ private void OnMessageProcessComplete(ProcessedMessage processed) case ServerMessage.SubscribeMultiApplied(var subscribeMultiApplied): { - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.SubscribeApplied)}"); - stats.SubscriptionRequestTracker.FinishTrackingRequest(subscribeMultiApplied.RequestId); var eventContext = MakeSubscriptionEventContext(); var legacyEventContext = ToEventContext(new Event.SubscribeApplied()); - OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); + ApplyUpdate(legacyEventContext, dbOps); if (subscriptions.TryGetValue(subscribeMultiApplied.QueryId.Id, out var subscription)) { try @@ -783,16 +836,12 @@ private void OnMessageProcessComplete(ProcessedMessage processed) case ServerMessage.SubscriptionError(var subscriptionError): { Log.Warn($"Subscription Error: ${subscriptionError.Error}"); - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.SubscriptionError)}"); - if (subscriptionError.RequestId.HasValue) - { - stats.SubscriptionRequestTracker.FinishTrackingRequest(subscriptionError.RequestId.Value); - } + // TODO: should I use a more specific exception type here? var exception = new Exception(subscriptionError.Error); var eventContext = ToErrorContext(exception); var legacyEventContext = ToEventContext(new Event.SubscribeError(exception)); - OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); + ApplyUpdate(legacyEventContext, dbOps); if (subscriptionError.QueryId.HasValue) { if (subscriptions.TryGetValue(subscriptionError.QueryId.Value, out var subscription)) @@ -822,11 +871,9 @@ private void OnMessageProcessComplete(ProcessedMessage processed) case ServerMessage.UnsubscribeMultiApplied(var unsubscribeMultiApplied): { - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.UnsubscribeApplied)}"); - stats.SubscriptionRequestTracker.FinishTrackingRequest(unsubscribeMultiApplied.RequestId); var eventContext = MakeSubscriptionEventContext(); var legacyEventContext = ToEventContext(new Event.UnsubscribeApplied()); - OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); + ApplyUpdate(legacyEventContext, dbOps); if (subscriptions.TryGetValue(unsubscribeMultiApplied.QueryId.Id, out var subscription)) { try @@ -843,35 +890,18 @@ private void OnMessageProcessComplete(ProcessedMessage processed) case ServerMessage.TransactionUpdateLight(var update): { - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdateLight)}"); - var eventContext = ToEventContext(new Event.UnknownTransaction()); - OnMessageProcessCompleteUpdate(eventContext, dbOps); + ApplyUpdate(eventContext, dbOps); break; } case ServerMessage.TransactionUpdate(var transactionUpdate): { - var reducer = transactionUpdate.ReducerCall.ReducerName; - stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdate)},reducer={reducer}"); - var hostDuration = (TimeSpan)transactionUpdate.TotalHostExecutionDuration; - stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); - var callerIdentity = transactionUpdate.CallerIdentity; - if (callerIdentity == Identity && transactionUpdate.CallerConnectionId == ConnectionId) - { - // This was a request that we initiated - var requestId = transactionUpdate.ReducerCall.RequestId; - if (!stats.ReducerRequestTracker.FinishTrackingRequest(requestId)) - { - Log.Warn($"Failed to finish tracking reducer request: {requestId}"); - } - } - - if (processed.reducerEvent is { } reducerEvent) + if (parsed.reducerEvent is { } reducerEvent) { var legacyEventContext = ToEventContext(new Event.Reducer(reducerEvent)); - OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); + ApplyUpdate(legacyEventContext, dbOps); var eventContext = ToReducerEventContext(reducerEvent); Dispatch(eventContext, reducerEvent.Reducer); // don't invoke OnUnhandledReducerError, that's [Obsolete]. @@ -879,7 +909,7 @@ private void OnMessageProcessComplete(ProcessedMessage processed) else { var legacyEventContext = ToEventContext(new Event.UnknownTransaction()); - OnMessageProcessCompleteUpdate(legacyEventContext, dbOps); + ApplyUpdate(legacyEventContext, dbOps); } break; } @@ -902,11 +932,15 @@ private void OnMessageProcessComplete(ProcessedMessage processed) default: throw new InvalidOperationException(); } + + stats.ApplyMessageTracker.InsertRequest(applyStart, TrackerMetadataForMessage(message)); } // Note: this method is called from unit tests. - internal void OnMessageReceived(byte[] bytes, DateTime timestamp) => - _messageQueue.Add(new UnprocessedMessage { bytes = bytes, timestamp = timestamp }); + internal void OnMessageReceived(byte[] bytes, DateTime timestamp) + { + _parseQueue.Add(new UnparsedMessage { bytes = bytes, timestamp = timestamp, parseQueueTrackerId = stats.ParseMessageQueueTracker.StartTrackingRequest() }); + } // TODO: this should become [Obsolete] but for now is used by autogenerated code. void IDbConnection.InternalCallReducer(T args, CallReducerFlags flags) @@ -1037,9 +1071,9 @@ T[] LogAndThrow(string error) public void FrameTick() { webSocket.Update(); - while (_preProcessedNetworkMessages.TryTake(out var preProcessedMessage)) + while (_applyQueue.TryTake(out var parsedMessage)) { - OnMessageProcessComplete(preProcessedMessage); + ApplyMessage(parsedMessage); } } diff --git a/sdks/csharp/src/Stats.cs b/sdks/csharp/src/Stats.cs index 3323422c32b..d4e5cd1a4c3 100644 --- a/sdks/csharp/src/Stats.cs +++ b/sdks/csharp/src/Stats.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace SpacetimeDB { @@ -137,47 +136,66 @@ internal uint StartTrackingRequest(string metadata = "") } } - // The remaining methods in this class do not need to lock, since they are only called from OnProcessMessageComplete. + /// + /// Finish tracking a request. Assume the request finished processing now. + /// + /// The ID of the request. + /// The metadata for the request, if we should override the existing metadata. + /// - internal bool FinishTrackingRequest(uint requestId) + internal bool FinishTrackingRequest(uint requestId, string? metadata = null) + { + return FinishTrackingRequest(requestId, DateTime.UtcNow, metadata); + } + + /// + /// Finish tracking a request. + /// + /// The ID of the request. + /// The time we should consider the request as having finished. + /// The metadata for the request, if we should override the existing metadata. + /// + internal bool FinishTrackingRequest(uint requestId, DateTime finished, string? metadata = null) { - if (!_requests.Remove(requestId, out var entry)) + lock (this) { - // TODO: When we implement requestId json support for SpacetimeDB this shouldn't happen anymore! - // var minKey = _requests.Keys.Min(); - // entry = _requests[minKey]; - // - // if (!_requests.Remove(minKey)) - // { - // return false; - // } - return false; - } + if (!_requests.Remove(requestId, out var entry)) + { + return false; + } + if (metadata != null) + { + entry.Metadata = metadata; + } - // Calculate the duration and add it to the queue - InsertRequest(entry.Start, entry.Metadata); - return true; + // Calculate the duration and add it to the queue + InsertRequest(finished - entry.Start, entry.Metadata); + return true; + } } internal void InsertRequest(TimeSpan duration, string metadata) { - var sample = (duration, metadata); - - if (AllTimeMin == null || AllTimeMin.Value.Duration > duration) - { - AllTimeMin = sample; - } - if (AllTimeMax == null || AllTimeMax.Value.Duration < duration) + lock (this) { - AllTimeMax = sample; - } - _totalSamples += 1; + var sample = (duration, metadata); - foreach (var window in TrackerWindows) - { - var tracker = Trackers[window]; - tracker.InsertRequest(duration, metadata); - Trackers[window] = tracker; // Needed because struct. + if (AllTimeMin == null || AllTimeMin.Value.Duration > duration) + { + AllTimeMin = sample; + } + if (AllTimeMax == null || AllTimeMax.Value.Duration < duration) + { + AllTimeMax = sample; + } + _totalSamples += 1; + + foreach (var window in TrackerWindows) + { + var tracker = Trackers[window]; + tracker.InsertRequest(duration, metadata); + Trackers[window] = tracker; // Needed because struct. + } } } @@ -199,16 +217,19 @@ internal void InsertRequest(DateTime start, string metadata) /// Present for backwards-compatibility, does nothing. public ((TimeSpan Duration, string Metadata) Min, (TimeSpan Duration, string Metadata) Max)? GetMinMaxTimes(int lastSeconds = 0) { - if (lastSeconds <= 0) return null; - - if (Trackers.TryGetValue(lastSeconds, out var tracker)) - { - return tracker.GetMinMaxTimes(); - } - else if (TrackerWindows.Count < MAX_TRACKERS) + lock (this) { - TrackerWindows.Add(lastSeconds); - Trackers.Add(lastSeconds, new Tracker(lastSeconds)); + if (lastSeconds <= 0) return null; + + if (Trackers.TryGetValue(lastSeconds, out var tracker)) + { + return tracker.GetMinMaxTimes(); + } + else if (TrackerWindows.Count < MAX_TRACKERS) + { + TrackerWindows.Add(lastSeconds); + Trackers.Add(lastSeconds, new Tracker(lastSeconds)); + } } return null; @@ -229,10 +250,61 @@ internal void InsertRequest(DateTime start, string metadata) public class Stats { + /// + /// Tracks times from reducers requests being sent to their responses being received. + /// Includes: network send + host + network receive time. + /// + /// GetRequestsAwaitingResponse() is meaningful here. + /// public readonly NetworkRequestTracker ReducerRequestTracker = new(); - public readonly NetworkRequestTracker OneOffRequestTracker = new(); + + /// + /// Tracks times from subscriptions being sent to their responses being received. + /// Includes: network send + host + network receive time. + /// + /// GetRequestsAwaitingResponse() is meaningful here. + /// public readonly NetworkRequestTracker SubscriptionRequestTracker = new(); + + /// + /// Tracks times from one-off requests being sent to their responses being received. + /// Includes: network send + host + receive + parse + queue times. + /// + /// GetRequestsAwaitingResponse() is meaningful here. + /// + public readonly NetworkRequestTracker OneOffRequestTracker = new(); + + /// + /// Tracks host-side execution times for reducers. + /// Includes: host-side execution time. + /// public readonly NetworkRequestTracker AllReducersTracker = new(); + + /// + /// Tracks time between messages being received, and the start of their being parsed. + /// Includes: time waiting in parsing queue. + /// + /// GetRequestsAwaitingResponse() is meaningful here. + /// + public readonly NetworkRequestTracker ParseMessageQueueTracker = new(); + + /// + /// Tracks times messages take to be parsed (on a background thread). + /// Includes: parse time. + /// public readonly NetworkRequestTracker ParseMessageTracker = new(); + + /// + /// Tracks times from messages being parsed on a background thread to their being applied on the main thread. + /// Includes: time waiting in pre-application queue. + /// GetRequestsAwaitingResponse() is meaningful here. + /// + public readonly NetworkRequestTracker ApplyMessageQueueTracker = new(); + + /// + /// Tracks times from messages being parsed on a background thread to their being applied on the main thread. + /// Includes: apply time (on main thread). + /// + public readonly NetworkRequestTracker ApplyMessageTracker = new(); } } diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 6423d8c3bc0..ad04d010a6e 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -516,15 +516,24 @@ ReducerRequestTracker: { requestsAwaitingResponse: 9 }, - OneOffRequestTracker: {}, SubscriptionRequestTracker: { sampleCount: 1 }, + OneOffRequestTracker: {}, AllReducersTracker: { sampleCount: 9 }, + ParseMessageQueueTracker: { + sampleCount: 11 + }, ParseMessageTracker: { - sampleCount: 10 + sampleCount: 11 + }, + ApplyMessageQueueTracker: { + sampleCount: 11 + }, + ApplyMessageTracker: { + sampleCount: 11 } } } \ No newline at end of file diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index ee9ff063df7..9368d6d83a9 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -661,13 +661,22 @@ ReducerRequestTracker: { requestsAwaitingResponse: 9 }, - OneOffRequestTracker: {}, SubscriptionRequestTracker: {}, + OneOffRequestTracker: {}, AllReducersTracker: { sampleCount: 9 }, + ParseMessageQueueTracker: { + sampleCount: 15 + }, ParseMessageTracker: { - sampleCount: 14 + sampleCount: 15 + }, + ApplyMessageQueueTracker: { + sampleCount: 15 + }, + ApplyMessageTracker: { + sampleCount: 15 } } } \ No newline at end of file diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index eab22149c6f..e5bbadfdc74 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -496,7 +496,7 @@ public async Task VerifySampleDump(string dumpName, ServerMessage[] sampleDumpPa client.OnMessageReceived(sample, DateTime.UtcNow); // Wait for this message to be picked up by the background thread, preprocessed and stored in the preprocessed queue. // Otherwise we'll get inconsistent output order between test reruns. - while (!client.HasPreProcessedMessage) { } + while (!client.HasMessageToApply) { } // Once the message is in the preprocessed queue, we can invoke Update() to handle events on the main thread. client.FrameTick(); } From 79de507deece6f193223539980b1c13256cc628e Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Mon, 23 Jun 2025 18:39:43 +0000 Subject: [PATCH 219/223] Bump to 1.2.1 (#332) ## Description of Changes Updates the DLLs for https://github.com/clockworklabs/SpacetimeDB/pull/2762, and bumps our version numbers as well. ## API - [ ] This is an API breaking change to the SDK Not a breaking change ## Requires SpacetimeDB PRs None afaik ## Testsuite SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] Ran through Bitcraft tutorial - [x] Blackholio on CI --------- Co-authored-by: James Gilles Co-authored-by: Zeke Foppa --- .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 74240 -> 0 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 68096 -> 0 bytes .../{1.2.0.meta => 1.2.1.meta} | 0 .../{1.2.0 => 1.2.1}/analyzers.meta | 0 .../{1.2.0 => 1.2.1}/analyzers/dotnet.meta | 0 .../{1.2.0 => 1.2.1}/analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 0 -> 75264 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.2.0 => 1.2.1}/lib.meta | 0 .../{1.2.0 => 1.2.1}/lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 68096 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 12 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.2.0.meta => 1.2.1.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.2.0 => 1.2.1}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.2.0 => 1.2.1}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.2.0 => 1.2.1}/analyzers/dotnet/cs.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.2.0 => 1.2.1}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.2.0 => 1.2.1}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.2.0 => 1.2.1}/lib/netstandard2.1.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.2.0 => 1.2.1}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll deleted file mode 100755 index 0b21d31161215797ba068881e3707b008c556bd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74240 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

    RXn{D}@q9PSUPoMOxpSp_9zjCHy)pbA{iBE} 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

      LsP#sf5`+Hg#eK41iGwChS8zt`}tL(X&d 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 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll new file mode 100755 index 0000000000000000000000000000000000000000..eccbc60b1a73d9d7cf4b5959337a31179e8a3d57 GIT binary patch literal 75264 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 Y|KY=903I0a$9*_<`wu_=|6$;N09@}KU;qFB literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/lib.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/lib.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/lib.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/lib.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/lib/netstandard2.1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/lib/netstandard2.1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.0/lib/netstandard2.1.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/lib/netstandard2.1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.2.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll new file mode 100755 index 0000000000000000000000000000000000000000..4e88c949fde12effbdb6475233f294f6b4084287 GIT binary patch literal 68096 zcmeFa33!y%`8Rydd1fY)$vQJx2|^%%LlVL&vMGT83L>(I0&c;83JL=WC>R36=2oClh>8f;xye4P%GuP(sR3lF9u(Xqf*)AjqSGxr2qV@h8}YHb5!+uF_nLbqYFiZzix0rM+M62W5WIyIu9Pc`<{lG^j`Bf~LyKD*Y3e=prs6@Zp%!-w& zuBff6t$~1jLm!n7z~GqlSBc@OsGWOG6o%4Qg+8+e{vX(lPI4nVUFwQI>6=kr_4#7d zatkX@`Ts8IVj{xin~N0Wc)a0Kg_=iJnQhCHRiT)DG9l(9_GVn%pM+kz#WFhU}( zZ##MgcQ;N0nS>pxL^~c&h_{&nvGFuuPEjjRq7f&YQ(bY}F(6nPA(O~#gw5>ch72)C z_!A_?>+&m$g=kfe_?m<{#IBcgqH#daDD^VJ% zJyr^5fl?Y;we@*^JXlzQ7i19_zt#)%vX zK5w5con)Mf3{&nmPBbFwywd#Aagp9&O%yE$qGci-Y@DUiA!~CkeDa<0khO4V7b$P^ zMhbm|Z#y1|`GJ1Q^g`E}a@$eFXoUH}UzTRjSy~9DJj=O7jsfF~9D%i6>hv-BrL|p= zXe~OjsICG{oPUW~EJjY`NSKtH+|o8Yk~kmPF!mV4mOm4zgu)>m*w@rc`wr>hU6awk zEK@IibV&DkSrzMCDr51#j(6C>;yH|GyMe)A2lD3c^B}fI4Q5Z3%5UA*S(1BWUsg|> z)@p(Ib$yX}1fyRT=?^Y%W0F!ZFY6nMFvHjpwC;JOyOILfx<-*|pgcb*gdGdYQ6iZ*n6ff)Fq1iP+KwV-u13kc!5)Ws z(+TB~c_T-eHeEhNA0aEwR*cqr>dbb+Zf3F@p1kXNxPUo za+LXVs&w4WpI`i7{)myoakcx7#WD`%*r@VKA2IdPibE>9O9IL6B0X_P-QA^~z3d(x z+S}dZ2jeLnu;VG*Y9aY`!(}|N6a1+0oQ=*OcsylB$H((5DNEaSAbI?7JCMF7wgc%3 z$5WUH-4okEq7d!3gGBnt+W`hk#uM*J9M86+h?B7Kmht?;)JrQ4X?)cuiP~1Z^vS6gnppMio!gf5!JXqv8uN4iwJV*o zV=dfjA^CM9WUR5H|ERHEgv1U!);RZ0jP-c{@wF>C{c!C{7KybhUEx>@6QO%z?Iudo ze(fd-(YAI6oBW7ZQo+hBllO2(^+z527}qQn!SI#^_`X-}^F<&m3#ka+@&l1dklIgW za6bcy;@wZ)65(&uAvmVO-$X#m0uKEv(%~uL7{%R}y$WxsDj>GeDlh?G!AU$>Ps>X$ zD@gGdoMik3QJez=x@Jel;&79{U`D#%H(+lHPloXZjoBz|O514?CqII4WdUDE@5{wG zj7f=HfXens@zsrke`(0<%bkJKD?c3C`Q`mszi}o~kBE_@5H7M(Mor>i!O7>IVBOIW z<1Bz}BV+WbEIJ-CU+Dl-Fa3?ctc*Sw4Ei`rrK7TbyS&myP{kwjU!v}jNs%4(~7m0eBp-uLZV2%a+G|p5D%Mgf8Fl96ZuLQ z#|GoR;^uobeB$|DD*?tuCZN!^-RLo3C0{lr`3e)Eo#dOaw4tLD#a{Bo?B|ZhV_Yz6 z)v++Zintyvbq&m)CFeYt@iO*Z6s|!auPn7vjO0`&fH@GEj3Z1>s=H2lH^40JCSABu z0R3{{mnCyH@@vT8Q9BRG%c&1O2B4`wLfYmlYseF6vVkJ^;~4p^3mOI7Ct#{!_p&q( zZ`N%U;R$Z1A(eoy+KBr}-?UOYPI>4Tb~p4(l10DVfDxRA1WE_UiR!IT-u!8B&LHvp}gx;u9f0ATkp10Xc{ilLnuT zj2&KiZ^E=zL5_`t$eTYPrFJ)pROaPg958G>aw1ypSzI|fOU*wi%^puluYDhezLX78 zK0j#$J7GYE4WhPTyH`p#!Ajg{?yzCb+HniH-LVc1fe{ z1om-hylvd1pz(2&DsbFb4%#KgO)Q;y+Q-LDTD9XQ<&6!J;i`C{M2d-_m(R>~OJzFZ zxK54(3|EyE0^9^ItBL0wX5D4&AsrSPUR-2t<74ZSLpuo|cCv=VPBsC%`0;Tar`iF& z2UKD_HSF82HFS$tZog{{v*2-%YYmuz5i#Lfcm+*KO_Q!Tydk}iD-LMky8YSb=_OyDdF*ELw&<(VB9MY6)(Wcy?BBPETZA+AcHDmnU_Uo zixhdvUb%n1hj*0k>2NwozSl%*VBpjq6ZgkjodeMZ^t>oK7hEs9F`NN*zhayT5sPuN zd->%o2zdF${ir<;*k%)*4|WEtC7DL)`YMXl*C{VGQE_xgc~u4rCTwhy zt(mcMR(cWb&p>>namv#?<$mX~d7jJWRhYa|#}oOh41%1SbwV9;F<C92fGFXj+{(orTDMN@OAAvD|JS|pO15> z6j*=iEA{cS|KV62IN2W}i{vu13U6)L4$eWx8>m@@cQgo|G|K1NSQAq(YB}2vSQAq( zAtFz~FlnF9M?Ykr$D1Se3!$=KcsLi(O;zMx5Uf2BgL!k$d^hZDEX$jF7Svu!X`vh2 zN;}myi&Q>E$U1U(El28NeX&!pYtbn5WjfFL=0vd6e0`vkUbg81zS-=nqo$)T1&J78 z8^f`Y7D=R33v%}9b`fDI5gi-XK_g}97T6{OzSGbI=YIu`g=hmOI~drd)yV!9Apze8 zIfxWB5_VtSp|U)=D(^BI1YlC|*e7JMMUll)1bJ8fN@mHf{cLl8U@NPk&0P437a|C5 zx5YmfTq-T~%&UC>1vYh`BjhGZ@@scMvT`UAO-SqRkiApc-0pUi%+H_+=LPeYViK8f zelWj0GnkL-m$$=kh{r&kC)YPkxFA>nRYAy!J|L=p$S#<-6mOL#To^2bsxahI6}B4R(d9YbX%yE~=naohYi} zU@=t1p|og!QMoD45LLHeH>kRW(xa84`r4*EQ&io9-J$9p%7`8(s!yy6JGu#%1WTYQ z31vo471cXdg-zUqdjxwx)gzP@T_CC#tO`@cgnI^iLe(>r9bF-+9ae>H#)NwXdqLGJ z6pa2tRQFmHws#XgGO9P~($TURuyoJ~~v<7N>7n&!8vR z_XmOcg(`ymY@ogf)Hm2Sh%I)&OQ8xzN=qpXdfiRJAM|pAz|I}=?aRX{zOguz(hm9C zq11LL&<>@wL+R~MMmv<*4rR4N+3irU9SXHW;dUse9m-8cxN?8s_vYuY-VgY_$5NF2 zAn(m`vLGfr7m+P@zqeo6Ao-3c=OD86L@D{fImo#ZgXbV#@sP0Ri3q1K%j7sZf-~W= zx(A_*$+py%M;`J?#gvQSM70d3V3;s{I&4=-Yr~ z^$Q~79v_XtCbAl&ZVkx!DN;9$<)u`L%FI>0kg1mU)GA00L2M7tspO&rD#aEqo7dOx z_@e6|DXs1As72PK<2G(^R<4I}&p!FRR^mcMV4v?o(7KC6786YrC)Z`AD-#jq(nKJF zQ|YouE=WugLr3Kt68nRE=0?sNAncR7@=_cy&KNtK>=i{X6H~eVBPk<0$)yi`x{8nO zDc-@Ozl51Z<%tj;H^$`>13uCo-qYy2e>+#eCi0!U=T<~8=gMNz54Vry@F`C8vD3;c zq1&&IbytbKbQGtN=&1DbFt;ry%S5h*8cT;Abzyl?JP;(mg2BQ1yI-3>=&$HYyVx?8 zc6U5%N$O=k$8vHhb&61H@D1|-=TvS2{z`Lgf9rU*$9v9=Q zO57R^M2#>5Bju=4S{sv6hff3cyj|vOkM_1`Yd+MGK5&5tAU-Ns*wGl==;nWuq%8yX zYheyt*RS01`c0edZ#%ZlapN|&*>3FEc7SVpbDM2b$F`H>wd!CDux-0zFbrIL42HLX z4su%q>_2L?nITY|+DtoVd@a&r6UwJ1)86hWmf8Hc|eh~EycqgTF@T$9DgQR{hAqQ9# z`GbI21p9KO9(J3RaQNixM5U?d-GatBIFVy9uqf^k3Hl@JLgrojeN6Tyn}x4*R-_rW zt19KgTVyISi*6O)Q(cKDJ<&gcMy5&HZp^G7#C)AvnPY>Y!#u-#QzP84%iN2D)S*kt z%KO0XSBB{Qkhx`eSIY1JaH0%EZDkOUTm}ip_2EOCIE@Ofd=QfJJGDEktX+k-=cKpQ zhhS5;4J0Pk^dA8K-taele6>%&y3{Nkfti7clH!Y;E~%NNSe`m9r934iQbR%84GxmC z+(w1kxZmLv%&2=9k#Va-cY8OCLHa{R!6wBYeFU0})Ulapu|HlI$pgMdLp}{J%s90a zFKk_E4qi9~QK?+tbt`uTk(?La>X1cM<{&CS3L;1X#up ze4G$mMZsqY0Zx)&@vpd`Y>BV-y97D|Hwby!dQdjQSDTVR6H>bt56DXGy0Txumujm~ zHaIo%D5}skb6^i&ZARSImm2njJhfp6A}!F{jLQ6Ne)ggbza<;lyzl$(n(hLRojo ze(krn@z}4xkYk7KPjA=0oGk3$eitW#v->jKZG@z6kGFS#T%zq_$s76pvE&Rdf;Sa6 z8kRQmJ3y?5enc!>cy1Vveb_`^lt2|POh94yc?F;M>P5o~%VbbL8OKT-v8}}C`rpvZ z0Y9(K!bCsF=T(Vyq{Ngx%!#~&_RG_qq$S|gejg8w3%2KB2=KPJFRweg$kk_Cwbz?h zK)c@u-k6M;Tzto!kgp=TdzE8%Q{li-S0^0p*jf+nQsx{sSP-{si`b50e%$W`y)jHwkSm!5` zYJG(?l~ikq&Z4r`((~2QYwkHmV}A8P&a2QS&NZGw7`&bOQt~Tu%X+PvNa135@cXAg zSr_@b8FmXqB;QX3%F=2NLt*NkhUfYAd=}GMRUoEkDOxt^{_=o7q@rtKU6$inD#>M} zmJd%2>FAXrE3|FrMV>(j+oUgon_GRQR*`QNY&a#dP!zJxeDQlQuRAMEPhzz!7f zISuPj7hgT;KHr%MDmCns17=n<0!mi{K~&_Z!(Guy@P6-6u=8}S z?l*6LC*5@Si2oqEyGJ~S_D#KXGx{g6c8_2#bojx%l`Co3BNA?ob$(v*u;2gHZI-5F z-pXY)>=6>Zft8Riyrt*Ivwl;O>vvpo{Y1n1ky%*#Fza_GJohi%_6~~mL~^mjG5IUI zdw};V4=z$4s5~#QJkpEki}CWXt90n7JP9|ap3Z+xD$o7WR8o1wpg{=l2avu_VR@!P z6rWxwUt)TRhUFo%u=X{UXB#|!YDvua62w{1oueLnXAc~g<J+re@hm|QRk#l11I+5 znF}2bUPEzn>gk+Z!!M<&q#BArgAksVNY4{BJOSePG(?>fH53hNNM=p#nXKVA@cs!k zj3(DmVs%`@|3bT84RKph$2F90Ce@I+(Ba@U6gQ`y&dD`&q^YDDia~=A)=+w$sNsna z$7_f>Cu%4f){xAa+6LAz1+jlZ4c8~vP-1ml!*po(t6{bz_QUgxSGks@n@KffE_66} z4aLo=r*m=*L()`I4aJ~A2x}-kPt1I+5nF}2bUPEzn>goJ?(tg-Yno6pn7&HiB4W;La8qS0`UPIJ5 zQA5$NhGf>%-pLyFg!fOV;eE+9lvo|tuoT+;YFGhLhc%RLCe@I+(Ba@U6gQ`y&dD{z z$NP3Q6oUpKtfBNgQA2#DO4JZ_PSj8|tRa~-wNJ2ygW&xWYWQMu4JB5`H5>}bD_h*Ybb6`J)M(lI8vHQnulW0AcQrPo+oN}62$R&h&m@~C>qv~%$nNW ztYHbQnSL%UxMaR*VyHI!~9)sVT+;ovnCH>aM?$u*oLO(oS(3>t*6 zhSKvy4NrzRUPIJ5QA5$NhGf>%e#aV4h4)XWp*JPzgj!;CTtnQXw|@;!f~doJDBVn| zA#j%&CS+Wl&{9HI_uDBVn|A#bQniLAzfKuZ5_?8cH{lYRFvZaPS(6n^RBct)R9!k#>HJlA`yoRWAqK2Yj4auyjy_hxpHN1a94S$tfLy6UK4R3~azZ%{O zQHM2@ZYI@`xzOR@H550ep3ccNyiJ-)s-YM(2w@GS=ZPAg4spDOsB@x*qG1imtf~DS zYq$m8KcR+qC)ZG7bzH-{q1~^Be}t&R8cH{lYRFvZaPS(6n^RBc5O(oS(3>t*6 zhSKvy4Qn8d*AR71)KE06A(=I`kFkai!TTrF@R{TqO014+*aGc-HQWhNhc%RLCe@I+ z(Ba@U6gQ`y&dD|0B~2yOPz)M`u!hoeTSK|thtJk>2ZejzXIjeG9K|1J;De}8sH5=0 z{;cZox)`tD;`K+o@a2!%jn~(BWoX>MhSy-c#^ZG|Uii{R;Y&pIE4+p@fvlP%y^RdP zC6BtBqI)2(l_u?m0#=xhKSRuGZIqyzB@4F9Fd+$>61u+H{Jw>oFLM(D4ip5 zU#D%QNarP_A5vN>()kJLSCr<6^z4LG?&=8)*@vW7os*EteQkjuABl89LRv!UpGCSb zAss;JHjzdX(ovM&D$+#>>10YT7wO`J^fZx{HLR*lh!#>be-%anHDs<06rH$gNkX)N zqA{zMCPX(<)PL2v3DNBoby;;@Li7Md?Y|k6@2VViucPGIYJ4{+UlxUPf;qTDKL=kA z-j4F|VGECa3?ny~3r#M*B;;clpQ5fF`xFKq;(#U(&u;K33|yIoMy`&>pXzYzLm0SX z42@j)jX%`kvCm+Bx+ zD)EOo((SVsTd9%L@A$JE8TQeOKTsnlmGMV8GVPNWTd0v!rTCK^S@yw;+o+KffcS$P z*-<`sv56XaTZ=!(5wwq8G*VM7nzqL{LiVW(tWD%ITQqozW2hv72RXv_p$l2fP9AUA zw(Hp!8H$Ne>f~D)S940_O}X;q6j&M8vfq^zS{YYzs(rxA>11VG$3ahIE&~=>A(wH` z>k2ztAy;wG=L!$8LN4N9iYx45ggMl__nw4@52h-Z5 z=~l`$987PMW>_iLa4@4ynrWq6#=*=sX_l38B?q(Gq}f)=#T?9TlLoDn>p2)~lZLF6 zOF9^8lZLI7t2!9AQoDxbyYGP*#k#j-nd7_f^%!AaJ?TE*+Ys9CzKhzv`+gcCx!*~i z*$l)kkil&GX{c|LZUKB7ik0txB;AhxE@0hzB8!P8(it%$hk)3x?FTrC2fs?sXnT;c zVK+=o^(8`dl33<>P64{P4g>`!GmqN*1^>8g*@6QZtsJbyoL{OC>v>b z=W1FAPuGb>((U{WABtT*{qy62>cuVH;C?d(FvO-_Vh(7|llz9mt+Z1e-T?yV;};18 z@?i$vlTn3!9v1Is*L?#EOueMRga)ReTg)#|mXgPta`A{|{buMJJ_Z4QyYSLcd5Spl z37B}fdEW$fUjD`Jn|KRnB7Abv@CJs+r*LU^^MpKc!zU?S0~yeS0iSe9G{H7-X2rj* zIc+zgy)TW-!AvonDUo4VmWdd+L*s8^FgIcF*Y>?AsQs51$m(|^>}OC|>-EDxwgT6n zeK&h{stt;P>{%UHglaDp3)#Oqun5=wN-ShAJD`Q# zOh!+eFj_0TBjGO{uX6`g^s5-yZ(#qSBJnB=nv#c#OI9j%HI5%)gDaV~q;}rIGm#;F zukvE08vT$>pQburX@5(zf%NVVWy!s0zEO!e?oP^8tnV&ig<6didN3pUEkOY$9Hm)a)}-WDJQ@f>$TJuwBYM zg!ubBWV7?Be`j{h_o+j&h0aUgke8)K=Hu=joO?f>?NgrY(j1@qCPV0PSwizOg)XP$ z8q&d(-dFG4Q__X@OMd|JGtz{AJ4@(QY0rmz>X+$4*B6T9 z1ts*WREaQzmSwq9i+t+yERkHAD%!2I8I`*t&!@g8|21hS_iW=+Ye_d#@+@OM5*DwA zndu5G{PC3d^o<^$I*XEs5xF5<#8wUsOSJ7uY#wDsooN3DYCp*>D)6c6Q-zMp*nply zs68!5;tVMg`D9igCn%C9=#@g7J7`lAQpo7qT+s$trLrR7$FOg&uvg_Fk<88$x~xDd za02Bw(6SGE_-u~Ud?{nzkh&ZEwrr``-zaG+@{f0r?7&nVGHbMD0g`$8-a_1$7*S-xTx`y`K4a_9$pDW1!oXAv&M@(h<-^ zTBgWv>HvM2Cc0GlRTZE$jF}%#@FqK!q6(puJ3a`VgouQMM{3I+Z9WD?==^#4;?;MF8z`QH1DI%-K=6 zi@IEC=-x>mZ3OjEtC7biYP6XRRH0I#%QBJC-2i2h4mshY=Z zKMhHgK57|t{!Zf8SFIrOc$3j{MS}XNOQ?G-M^Jxt9nqe!pn+H$8a>-tFxt$*zVIab z*%$5226~&8i*v6FEx>aipQ??p{32&22KjLH8Fk$|%|w*L)#r>7PMc{~BA;(**$kxc z%&1?B-#f~pOf9*84zvKeAknp2&~TMYbTQEgRY(*Hi|z<@2vJXCQ8Cebv^)YI`6XtR zi+T}lcTsPm%RJVvoan!c^o65YrOR;g3;YUth% z&BTa}QL}XbXfEo$0BBA-bY?p=za3hTgvP4H+KWX#6RUo+8mE?OgP0G8l-i)iyJ&Vm z&;+$E$?q6-RT7${uBG2*EZ;^oS=~f588I8x6mC5krqy)+d1>9$R`A`_ODX4r)|0=M+M)i3oD*Uf7Mz!M zLTnmnH?`5f5_Al;+vs}{C7-7}6eVtm;A@%AI=f&TjW<1 z2|u3NVWcBMBFPM&mo_c7DO>t{SMCL9eLiSHaxo0X9;@saOfV;*@1h| z?!7)~eUa~K*xZ?YALzrO$3SNXc7dK4cm_0__9|>H^hsqt^1TIqA8A2K6Zl{Ic7wi1 zI*#-t(nq`^f0=YL=^3O~lHNvIK+C?QpHQO74G6$-tf=vC01 z;Mbs`u+Z*CXiw6&wD9kdjwG!jeS~y7X%;PWNWY=vzof%S9|Rq&4l}!bd1|40EHzIR ztCw+$`)z68r)rg1bPBej&pg8S$la6TQ(Z}apZ_}e+d(xh@{0BzP@mGd|G{Vqos2hb zr7kEq8)sTt&4{BX5PMM^mHM?>6-T1GERN(%=hty0QErK&Y@n?c`Io2SPENJWMfqVt zJ6+T@oQ?CK=aT#!^|q@U5g6=v)ZVymSh`1j>*_|Qo#Ei@vYW!+1%4kaan5HEGRnpo zQ=zLXhAu^QbJ6*sM@)+9?V^iA<5E)8fFwV^nh;0N;M{7aYq_OhRC++oj_c5xn%533 zZikk)L#x}Ni{mI8QLeMdf3Ih-lcpM76fP8Wn~S;?X5$R-?j*l-^;8@^gY&`HUCX1; z&rH=C*Np@EK8_})XRF-qwq~bgKZ0j44sntA;psGsI444?PaI|A>5Ze~Xj*z$o$C6{ zFBf7wWK(AY!t|=%5dW+~9 z|D#32oP716i<*H7)pxGng4AW6B9$Q@$J8$66pZs0sUnNCQ!v57nJWKwVU3)Yeux@M z-8$rVjJJy#6-QV#YCMswhqKbVs+mM<{hM;vr*u=ZT~tkU4$%jCd(Oi2Zfa8;)une= zPZC|@UmjkbUZM(mNb}eD=L7XrXIZ4K&t9E=s9Hj_S`~J>Fg>E~C$g1@sJC6ezZG5z z-B+%q)TOujx2t=!XnA_6^7gbXGy|2ZETUaX>QbSGxJc?!p(Yc3fVy0j-dC+5l5DR} z@29RLl597o4^TI_sG4Y#>nGU`P;bZ4t?2{#0J!A0JiH}+kgD$0mhG1G!Rld)knPs= zA?gJpo9$4QgAWEWVlwVS)nP=dmE<>64Iz?o-;zE|jd4*k&L?dU zM#rkth$N#wrB6~<5ZMtsPHiNzBQ`~Cc9D$O6t&g$lZ>XQzsAwa=~GpfT-M--y_r5u zO?1)x@SEw=)dnJ)(TVB>BAd~P>L0F7#^^-#rR(=-(VOY`rlrirYzCTztGa@0MklL* zE|QE+R>u%YMt?~^MafT1qc3V+{zvJjstqpsefVGLr>SRM)W!Rs^x5hg7hO=4no*+$ zmy6$8%-yVvIjWNA8g)!KH)F0^=Aw;2XQ;belo9Niai(f<(U@?*jI-2-L^i*()R#nd zO`oO8`$!9d4$GLQMiSZ4oUcX`$!HGGI9p9}Q8Um2HG|0J9#!*QB)Lb`8Y0QPDr1ql zfk<)~pRrgq5y{vdmr<+kCX$S1X4I(%U9=HsiQ3_!jNsgirRo(To5Q(kFOkjRT-CXv zEr)Y5&QpDfY!1uR03ykuE@Qbm(nZZc_3CIMn?r+|(1U) z>MD!;zY2cmiK!c1v^Ch-8&jKzuJQk^a9ze~wJnY=%~+#8u$HPk^_q;e>PsS<(OQ+$ zS8}*U%?#cIU3a1j)Ux0$8S7MESJyLm2ha#tR~g)zv0jaL(fHH{fljrS{-bktWL%(@ zxTpx|BDH}?YW94_CF(9$w>yz+J<$c~ z#=?JPT&J3dt|(ZXcaHaZb+^@V9IjUnTI9bs?>o;8YP*Y`z!=@2o*|NP_%7o{^-dgl zGH+6!x#;MejLcsvZ+}+aUj+19RYY_F#%OECMkW6@M%(VaQLQ5SKucXVsw-V2b-7vH zMr7;Kq;?Y7x-_YO6G>ePGdC&k0NY+O(5)(q$kydH)y+jxm)q1(BB@JB=4Lg8$kyd{ zbrO-S%N=SS(N4ddYuurh5=ri*nRlp$I2xF_MXisc5t(Zd5`*>Xf;N~r<&C_M0Q>`t1)=%RB9*R@tW1K zL{f?QnOoIN7c~Rjs}>O1O5CrOx=1QzNO! zCL%fSY0TWFw!~4B=VA2_kv$`OL_I-tf&VRXx5sTD+a zhWtsK@VCo*YTEA1KdF_}$$s|F%;(i*uAj{77u7v3l6n1S^*WKA*Dt9riEJfaQk8=l zljmSBsdYp$TffVENqyw%B-@u&_rt~V8h>+<$$CXia?zteuc;W3ox5+S4MbO|<8#up z-cUPxSF*?vv#Yl7U2`!ysW>dLy2S@?#SAs`VmRZd}^;6LS(DER|4X1mscv7KvKc? ztqQugv15LqCerU3)x~>H)(2{li)QCPl=Y!{IgTFB`Z(^_#k)X@b%=$)6bdmUdt7?gCd*7**uC9ysqpa`L1#!R6vi_qkPx9NR z?uc7{o%OwHj$7`_QhHmGrO~g&Eq&RJelKpBk?qkRC0Y8kQ)&Cz#haU*qSIWoJ*{)L zU+1_;dL7Vx>Jv$OSeNtPkKHEua3JFHvd zmJ_pcbj~P+zYnyuo~Qe|sEc=ccD_E`McdO(&MwfENtT`TNpZ_L*+sf0Zh3ZgXMIkR zWfy&6+_EmatNvx&^8D;#eO;1ecikMfT$5d*ABtOEoZUn3OtS2yTjQ2jWFM;4Xq&_K zwCl4Yy0eQUqf$M@MP0l%XP4*9Se`*0m`(e|`F{}8>wMbgh<`W_-XTZikGxL?22 z;o2F~mfxn-5jyB1@jFs?A+mlW^wJZ@PPJW+2=vYe^^8n>JnoTanJw`Ds$c#pvx2ATSd!&zeIJpn%jx=oxL8b2(`$)rMoaWBtd`K023n?1AhPf8=j){|lK1KJ^;#mEQN7+^5i)uu zxI+KYwUmq+^ut7w(c8h5`p-m?(VpNc-Rk;v@qQYN=|RUzU+@_y?aSb5eUpo1_N>)^ zC9-3?PJiy|x_I{m*XhhjZGI`C^}2xQ0+pQ>3|*+l6YbW|2M*O2>8V6E%EkJ4Yl)s| zb+N7?vh}<~N3G8PinGjfi9XLo?>e1Am*^Ogt>-WFChNy~{zCtqNb1=wv_XICqGq7W zbmno=Pg~E+bsrZ=Julb8iKL#VXI-JkScH0(g|5^KTuV9cxk}5;v-nhpUJnRetuG;x zdJYZ!N?&aebR$F8=q4hY(Y5;bR_E{QIVyCmzRyKNJd=Q0h-^mJ>9?&PGrCS^OqTW} zqZy&=b)k!zfo{}&h-^l`))QSM8U0$%BC;9%M%P#*XL6z6>J6@?WYnmyCX$Tig*NKV zM3T{>(9OEpB4*U2w-ecnHt9cEo&P9gv`N3}qT`X#CjB0f&FB{Wo%Lfzx9IXIZ5b^O z-KvMU2%icGk3Nk*51?$S>Z z*^GX#|7;O-cVzuR?>srbf zy{xAbNk&fi6+NHGX7s9FW)U-bO`i~`{|br%;k1HG*W5ZPJxuAbr|$>?2u8j;QDJ$;r%$S5b=s;_V@C8OQ? zdLqfFDEt?F7m>|qkKSexGuo@4A+j00uV1q||K-T&ef^$`u0uxe>yLb z>psvY5J^Ve!yoF?UDOQpu|Ai`X7s84m5U^!PjwTK&FHUsi$%z&Jp4EPifbtu{awF9 zBpD41f2O}6vKf7jFF&O(a>mjU`iIUUvKf7$i>%I{j*Pz0B`(TEMqlW1BAd}a^LPr575+*;==#a5`$oUvBFX3*{UMRf=->Kti;&Tn@VB~9ZdG*G z(RaEVkz{mC_&<6ukxtF2Z%UaJCsuWM^H-%yyAvgr{SOY(`^={1oI~%o6#}mZHt)E zMDr<;&FEP3wbl90K}N@#?_G2*GCJ1yXDj^Kj3$|KBD;VE#)a8T~VSq6wWYeX$wMFvS)z zqnV~Jk1HUAT}L%$6p>_vSZz#QqPTuTq-oNc-g z*;%*19N{9#Xn{F~$Y!+A9B&aa>YNib4X&k((IT^+NHQwPS!`|~vKiHy+bm*6b>==I zo6!=p!|MEv*cq0XXI!)yd)*TAGLg+_srknGF{7ns^jw?6qeZ1T=bA|_Y6e^MTGP=;bL}W9%$h>V4GMbokvGJZMeX+Cd5`(Yx@h2Hg%lU=rPGmFMVEPfsmHb&b zmzv4*#8R$u)Z|=daux`(S1T?zV~KX_7_L@aVI~pTs})z8$?ed|)(`FBNenZGXf1wA z{}bPprpZO;sb^EKGJl9$YIU`FnrOFPguCy4WuA4>_@YP5ugr{v(wE(-zw7igP_;$+ zcZFhkrmNf2>3QguxVo=$-!j*j9WEM__rAH-JVRu^iMh_aOtcnv{eI%R&QwI1Eqi^v z8A4=r*Bg9Qrq-tly((Miq=3+=X?Uzu<&y75YPBOfiT1$)p-*^(T6tQo@QWyqB92j3 zVtFfHS|m0?4I@aOL^71Ve<>9ChoD*|^OYfyOoWa7(`qp#XG3Dt@9As%U}>^%GM{Yo zV_Veff7Z(Xd-4DO5cwI@ziljp*Xkt9AET}g3%`b=d@AX>e34jc<#rT;UXlO!Tx=`J z(S8{7Rkrx!W4;oUKG^=8Oy9RS_daJ9PmoUK>?(rRs9nr7nSYhDy(cVy<$S+pB*vn(bRZu1(vYn^8}rZe>-I`Ttp4ww3=f(|WG)WZvdm!5pnNpB4CV zxkxpBxMtTR?HE5cPTNddj32|%uEb)C%Hz2a=_UAXHR85z}$d~$v4s98D+(Tw^b z-v9 zp2qKl*K)kN;930ccrC}P7oK6Nz-u{P15`1d9WMr7td3N8MhUNRcuj!yCcLKNIsH@d zEd4_KZ#%VkO8;EEHsOC1T!TkB-o=yo@2WoPFNpR5o}2$f^;3VxQ}JIQ>Q{Ik{#*Rg z&pvgSGJ3G`>BCh(4^f$Vs0!&}Do+nro%9IRMIWKM>myZ#9;pWCO8ng1C^bxvM%*#@ ze*?$jS^06eHSQ=iNga)+lqaau)iL;8j)`i%I#!(z=>_UIJd;0JU4|#2uS9RJ!I#@N z;92M2sOjovc-)HX8n@$XySvm(bq{_6;9hl-dQhFL9>EXbZAWIi@bvN1s#^UCPXhlL z(O<>?C0MHGs5fxzh2twYzKEy$)wAY|?q8 zi$QZyYl(9OXpy>}{ASVzK)b1r$&b=!=RJe}u}|);*}^*;uYlx!vr(_bb)n5#t_Mvt zrs!$2S?|L2pUv77J#UUT)AHUjck5}m&hr55eR#G&=tlKMYQD3Z{BHG`zlXEJ$n!bE z_j4ZO(^V^sJTbSz$kTA^Oh%`Z!OQ*d>&$}Gvz?8qxo9ygCEC9cITuf9pPhGsqs_eh zOP#CD-wJPcQqB7CLym^_5$7gGxQV_uA?91oCfaYId<*4UDBnu?HaFS};clLw`9<21 zo~zAuMUyj&*Vzh_xa`_3;bdSYQEjq4fap?Iy>@&ac4)K zIqr-n4nOhraL&&A-Zw>GlJ8AfYz7u(fL>Qrlv1cq4L@SaF`I^^Y~!8Q5@8&8X?GiE z_y}spAVQO8jB^2=IvwLo&wknz>OHzHMeNT*oTKy#@-gtcG@iMH{9^FKvm4280{?ft znf#sLr|M-MvC;Syj2HEH{5AJ{di|P?twktkri5~Pt5P(msU#s%T1x_2kHa|gD%b=;h)2p=g@bK zQ{rv%oa0D@C5}AlF120ae+r|Jtz?C2wOb!iaEX7lX)OAse>~>D*L#KORwVbG3=03o zzrx|#bYxYoaAakzqhuW=>nPda$ZWZu9pv5WGBh-r14s+S?%i-nZCnD10Y%q9f0s zZ!|A^OkkoT&!A6q>;vJ`Z zAQSI1hl3ukP5_;umV%zFt^}=CzXzS8c7mRz-T*yE{RMQ9`Y-4bTDKn%cE475laLrHl9SHd4~$ zQjs@7?#q9Sk{x(gUzWFnZS8=(PyP=4-??>pFHy3aHhW;B)Avxa2R2ptdua0|&L>jR zm6jfAQb&uWqowDLu2=K(9WBv{sqIEuLYorWl)xsIUqYK6`WLVq2>G(SN?ML0t)hJu z?WxO3ig!+RkWW*Ni}U|lh)9( zhVmL(*3fdbkshw5&05IMELcnVI<~lu+9vuo(YFaUmlZV8W)rn7^xXmZ9}9L+{t_&g z|FL7=}HF{9elahg;%kruyA4Bu9;2HWyRgNV*B~l=NFDZ$TfH<+V`0gI+tSeVoyrf{jjpirQ9MwvyjN z%a5u3m=eb$efD}fsgm^G9`Wk!k)BkNj)f$YUgK#}PGOBlvaX?IF6lhl&!gp9YS&V} zp0ttjCd!*AX<}Qqkl##g3+WEpJWlx@@_SrwS(Fnw0xX=E46#5-9yP9YTqaSF{n=em^S#GO7zF^abEc(7stnOAzw^wH_{T? zlu%wmo1VT-sv^BNBp5r|RFYQFvWk{fv>Z#zYHDYb*3hPgHZ`=F3meQvMw>^Q7;Kj1 z#mKLv{aV_urTu!^H&VNiw23xNv}vNvEo^r)V{WER3+WD8?x5ukT0YKbt<>&@9IKBu zduX$VHt&=F7!=i`rIW(CrLb-(tQ+}mpxA||Euo}@+MeWlQ`Z#z8p>gngJN#bMx}CPrLrcetVt?sLcW;VZloo! z38nX>yf-MSLHQ`sDrm8jQ#+P)HfaszHRR`#u63!jvYvb+ZJNk8vGrTXKb9(Ex`X`V zqXH0lNu4zIoV1vdZlooY^ducc zNfr6ooXugM2Hg!mn1;<;60j&&8S2Vr8aC zs!3y{jifE4t)!!}WSv%LiTz_)((_jGyUFWpkrZc(wj23M@YtWTCGu)Y8p&@Y-$K5X z6u+kpn_|+IphRdTRUwH`8Dif^W2B9wEu^ia#bK#Waab%XNgF9?ajC>qIbu^uT1{Gv zpISohxs;QyCSOfHMn0A+F&jx+NLwjyC9m?tSK;#kS|?vjzLI<;`9|`MO`B zr`rxUM8RDss%J-;{)>|sXrlmq+ zwvwv8jNez}#pEl=SCX$LjgdBzZt5#BH}#d6EtKr+E0J5ttA30|T1i?>+SpIxH%NEjB zQZ-2AoT!zA*i!z6MGC2BD3 z2Xo$%uOwedzM3>fNsN3W`9|_B$x5-zN#zo1( z_GB1)LRv{lCHZRd)#PL3W8~KjlNQ$vlNK8(*))vvnS3j0@o*W_;^7jxlC+vMMtP%4 zMcYDoE2$d6o{;t!A+7WnA+1zWGG>IdQcXTa+DO_$s*d37J%SNPD@m&3CtGfLtYj}n_6qa=PM z`AXVUlg3CJNn1!;N!4h!OIk@AIt&m32o+D~*(FI!an;A>T@>j+O|OM@x&9YrfxKu1#DOcm!E@_YP(n^o< z(n=*IW5!D>)#PKOjifE4t)#^hq{ZS1Y@M{4G)8%&OGVp4`OXQ_%FYSWN-HIMCrB&m z81{s;lC+vMM%qZ)LaHWmq$bjyw34)%@;MVF{+x*tKSoK6+I179l}7R{q^+dtSjHi( zB&{Zmkv5XH9xE-jl2?<&-ZM#B@l29diYe(aN#a*d63c3rie-%2M$#72R#J5w+a;|e zttO3;ZaPllZ#qumw;U%iTPWXooV3zPUQK3%$)c@vsYt3RkC8T#wve`xswwm$tt1^Y zMcNuOMcS&SWX=@UYKlZ|q@;zkl~hd?d9h0+TIE!>OBy3>B;7Ps&iq@*?lR86NnY4vo8P)$BY+DO_$ zd8Al$3=zGN1J7rYLaX&}^To7Cc-%o|{ zf0E?lzK{a^&jE#yc7mh`lFs-aAG$%(9g-4AdO#Av=uN;~A;&;73DV}_8afw}KNOq~`k+T_dKL;j zi;|jb(OQ0Ck;wm0unKfZp~Sf@cOB>)(%W(`A}_Qf`76Ooq5Wr`P#eM0HJ&T>lLS52 z#3j!=H^uqCI5)@n5uRJ){EQ@ik>}31{A+yc+tyZZPlDf&B)=(%FHGXglK4kW!uQ1_ z{$ELaN|OBA5Rk^4%L1PVnZf^s69(;qIjAw$a=~}UTr`+#g`mAK7mX@~mBEbb3R;2L zXmFQO3FvTG8O)?ZK__BX8qB#e(33GU4eko+3wkzYr@@^y0}=lQP=o*6@-XoC%DqVV ze>n~ZeFrnv;4Y)#kiQ3N)VG+scsc|3AsKa^9tHU_P@~rCD$on`SV%4eHR{*;DA3>N z@sRu$)Tk}`7|=WQv5?#aYScseIM8i+3M3DM8uhfE2KtPi4#~5iM!lg=1btJ_garRr z2KbNkNuVF=Qy}>S)TpoZX`tWe*^vAj6#wa$sR2zfb0NW#@ZfXJnV@-Q9whmoM)fdf zgZ4BFAn65a6rMr`9b^_mau}$=|DRF^T4k0(G6vM(u8{LUr<&!EOanEl+SG&2HVu%R z4r)}?tO8wRRztEF)TovCCeWx=W<4Y^P@^t27lK}9E{5cnphn$`a*#>IV%jR0pSIzYp{}Xf$zMEVLdMKXE%Q45QK~9-E zU0vhtgPmm)euQ+6y45=n^fvEdptpMu2i@Ww3VN4!IOrd|M_|?rz_?fPezNJ9Gc}ko zwYVQErY^$w|JSLF_+L8i#{FU2anILo+==y%|EImHkB#HF?z4NJB&DXcC}qi@Lwxo7vkXk8;%JkD@>+-Oii$X5PGc z^XAQ)z1cnWCQh&A@K(9~)rbq|w*KDw zmW5xiu(S3a`(5^X?f2W$_Az?_r?i&r=WNIJ?5p;M{W1HK_Dgs^?^XNr_AlDMY5$@9 zkM?(P#vzf|lUPptMB?WXf0X$9#CH>R^8Vz{BwtJZNpfFmCDl%SF7*qkZ>Bz({)O}# z>2IeGW{zc^&#YyBEA#uAUD@;5OWF18SF*p6{YLiRv-ZfYk$oc%kNn|Cvd0z4#wYw+ zlP6uG`~#y!JTs(l)^0yM^?PvEt_a<{7iaC>2ao*_)`EvH*B-)5dkE{=4`EH1#F{XP zHDMBK!X(y&NvsKzSQ93(CQM>Yn8cbei8WyoYr-Vfgh|ZLNoaZ!Yr-Vfgh{LklUNfb zu_jDn{3bC5k6?5@pj@=D28_Z=bx{2ro+i2dm!7j5D%N}2@!=l1cpb}p&w zf`88BpOd^&FRDi#B>hF4Qe*w=CV$=Jae7hcA2<0MhX3zKs^B9u{da}_F4%!?|Jx@0 zt||9d7V >zFE>je6Clb{{bLcO!Mw&n6u8Eqq3kjv7yXL>)wWF!?QfKB_*H`~=eP zsLvt)x#Yi~%y-lqNXL_}tM%01sc!n)s+WEpW$sw(seSmo6Q9@B)0t;nRSR zz5}1!fW{l}#|?Pn&qLdPhRERa?AFn_daLOkdsrPkRw;bu8p8H^kKe8IfZO!lxPfrNb*jgzg8#5wp*_|t92J(X|C01JARm3Xm%TJl)Kt>f{;XJ&-z}#TFcJ*x?5#oWJoyItZy#0 zohCUhpjO=rHZ^D07o6rBw3s{Nbpj;wt8=Yp;BF8;d1ywJ@L9o!{8mcMzb(gzsbjoDTwF9r!MDBvSHh`t+88z$s&L&7lJ#svx zPCog#D&ez&PuRQx(L9OMPpTDsLZSgd1XP-N0#sgNQUEWJXAH3vtx4DHoOs%b5HM z(rdJla#@wjRB^f5^&Of>x#3m(RtE$!T_#C1q#@#9K^i3hG5VJjH8O;Whe5bL+A*RI za-^MTwG3WE!l#QDjc_=Y2n02+qop|S!y+nyrVTQzA*QSG1|)WVRk$Fb)hz|pRk1t) z;EY0hnQPVSZiSuhOr3IJFq1~#~hRc>ZdWCZ8!?YED2jpUm`EZp*x3TK_ongYPzmE028SFqpGbdYq!wH6K zEp0XfXJZII+ittfs)~zp-u0KH$7 zt<_mZgS>JT?d6B1z24XqLK3_yw* zvqiNQ*`?IlVv34U*}yPWldP$i;b36uf);oON{Mnx&~`KyTId*JYHI|F^Zzy#mJWlUXc(t7$l<(( z3E--Qs)se^gx`8WhIuJ~d|0@q%Vn4vz!JP7)>+tEeV{5e+v#8e)i*JUP89+0Y=GZQ zUhSgz0_Ih<>Q*BRgIurf`es}&xL3QLzf%EOZqa0{?!rc;-mQvR(WK{EkQvS`Vm^RY z==26THSex=*Vk#c5iX4BBh0qGM})9{%U%%YP=azDXiJo|=u~Q6Gsd42AYy_2M5Wbs zt5|9x(06UX%CuiM))nopRL77 zVTVp)Bramy5#L1hLSm`8CjJdXr#@6_&Ov14hyD=)`|u-M_?V&XoM}}gY#eR@vCo>f zZv56TdEV_*d{1^I5iv9v-Ma`MMQUa~L?l_S+pRi{NiXW!Dfv+my`L!Q*bEU?jD!(e za@O2n^8$7pov4a$M;vEnV^29EW;`eT?vTSB+WtqN3q^!Ju&u8WFTg^_mx9#WzbF z6X8nel-~MAxJYPhtDBn$og5E3GOPw9u&lp)s>-ntjy|s$lU@wXaluO}FJcJIetR%RVr9=92-Qe6Bw72d?v{DlT>Q&ES^%XH9N?0qxe5ixg#5?)! za*Kn6Edjm>IWtR}ca70lz+)yA|3Y8L#-{98DR9Fmw z+R=DaY_=nJsU54uW@CkCVLjIvqNyp~I>A+v+0{-c#aZ6I^(upWbYrI@6G(2Xbd)H_ zz}p?OC`0H3#G|y@P}?=H;toU#$s99A&I7s*{IIgn(R8r9 z1QLe~R>Th4> zjzD_)am@67BFvx1${U0kJ;_i=@BdD_bxaD@S;O?gt_F$*kr0ku@Axx5!W8^9Sf5$WQlBre9T^c@0qs_Rt^7_NaPD~m-3)6V3nqQRYoa0M_l z8nyw$bw8HnHwq@pHe%V(kxCy#;qqleQ@pD>xB6k+S5!;5?Ty3)mDn*=FbtxVaI|A% zF_@^BR8tpREaocgmtNadOO|+5ch>?Xu_&E%snM=ul@1VJaj1Qm3&T--*@6puKJTtM z-FiTK70;$-x9yR!yj}DBR+C$!!657;pozWWf<_+2+@Ia4Ug%5Mv9~Gqw(QxHx2YR% zB3|_9v6*tYqHi6mb_;eZI+^45IJ7M~WHsk>pgx9>SgCRGn(c0&7O@lNln#5eO!ykU zFuI8Chw@(#Mmj=Q9l1FLqhEJ7R1F`!v}ji$iv!$-PEWZ3h6Zu2I|qweM;WXCRHRS6kffoedbKM!7(ZI>Bdo0g$NYd6lmpA+q zk15MiAH267&8Zgp+eAMq=qut`z&y{S4&PgSmem^bP#>!P(M??W?=gJmy@)HmoWQs1 z%lMqezaN2K8@S@M9?rh3#r{35tRG#31Qm=#3sg!(X{vyifNvu2;+yy;;0=sm8`KKk zgiyry>li_tm{9M=_s{C17}055r;yH|rFrQ5qe{K!ZoEzXeM`cP*3retx@s2vQG4g{ zt-aP!0Ne&~W5k(SPt1xlLE}Yfu_>*G7)r|- z!Ftr5TD&;0@O$UA2L3*H3~_^0Vc)jO#XeE44q9)^nEIl{DsZc)Q&cA~`m?Z~vlvn8 zfTL4a3csWMKDpwj7y#phC9aNKSLKS=Wdnm3K;!Dm6=MhZnq0fMZr~kGD)r-NL!~$( zYHSK^OeujM!gr3w0=LeNGBjER4KM$HfLG??Ge9U$^UC?ek)s#k__u*;02f*~z7a%D z+jSZJ(w1FDjnKA**L0j$S?rS*6VBG{JRw)U1YWd7AHAiYQV(p$l+jmc%wey-z~}O8z|fwL~ZMUnud;t(ZZ{-SlVF+a^oxjdFt$;Eg~* zMr563;1Qzypw!q2wAX^%D3K500X0*?>Hx}arV)02zHU zN7R)VHG~J$k&}a7XedqzdvQ{vjwqpbRT*tJDxMvnsX)H(Ay)tY6VvMCu+S+hq%tq^C{W#9~y(S1`$rJhpiH(&qsS6?jr z`_r%e{>|gBU22S|WYMy+iK4Pn0P=ZebEzT@?BNQ;f?R)WbYH=>_7yH$dsUiXzKZ0d zIzg_cb4-w{>l_p0+B(?`!XVC6S7_PWMiH&~`9+v_0(+g>lLOAin?Oo1CAAw=8^ z5jQF6MD9LHxi8=Qc{|^`neXXhh2E#6exW~U(nobQ5XRUtTKhEm24e4*tcjFq>{iJ8 zR<>vrdbbO`mp^FOed0;%rMo>_ih_8j+peQNspU! z-lV5Zdd8&ZO}cE-OD28Zq?b)vHEGSHb(3-wT&vIzOlsumYyB7cJ%cxDM%RGAu$S zMxIgNp6`7(nXw92(N^Iqr-NH^820*!j5W%By=jeQinhHMI$=w&18J#7jx-7s$k$21zzC&IieO+Pf@u@e&h0_B znBTAV>{nUfaLpJo#~`o<_p8LHm4c$7-;}a)6M*epE{7)eD;C31bxNN~XA;?o6g^Is zC9>I+vQxS2?o1+oJ%1f#K5OBnglHKisWTjEx*e&G7iS5umkm+=>(INACWTtPp6G#g z%r3T*>3r{%bPN0Z7L9nGj@ zE;l|tPCosjaJwnj8z^ayiy-16**M)vA`NBiv2ZXL9YPjIi7_JRPvPo#Ud%^|nbM_tW4=fgVp$?KxDjDNb%w1_|2i z!HtO~d$*u#dwhH|Go9VReZ}3>R+z4@f27bqTIe4y^ydrx(}n(-LjQcBzg*~FD)gT( z^e-3s)k42k=+_JVHvCJWzftI4heIj!Z{&Ml&1U72J_vgeQ^}^Gmx=vK#_X28UyWuG zh2HDv4(282cKj=I82PkHa468(6ow`>&Y_~$?tcm;#9{oh zO_6)I>01PATzLNo9DXmPa-|!87iW9_{e@?CbNB9zzBdb0%PdUSSEv&>y3O} zEb9%Bk|ZSoqzR+}>>{uWz-|J&N6^DhOFNYAI|9K8gkUlaTfzK7N9ZRh4<{tuA$vMP z``W9rdo9-fSE;>QTb7g%gQWqYDU63wh5iQs%M1r1w;T0Qkj@i4X!-=ftDh8JRFHxK z`dOru<(sfV3?3AkEA;*$n@PdBW)oR-C6UELSo!`!0ybZ`3L6D(JS&R$h8W5Xxyq7{ z$=w?OH?kQUOL@NkFiri7;PG%SlhgqK*8D>MQDJfm*Fyg@Vm!H=p5<9+51xVxIlBSB zt=By8-++k7rN%@rD1b=@D}u71&<|%Oha-Tk(Hb1 z+_E=hLpeS#iHqkT@GTs6N;?w6ZDO2w{{m|8{=pXHDG{W)1)2R2n&y3s2hU0c3dSvQ zyy7T(!FwYcYCLRhN0CC}61wDoXPilTML4G~L8`h+;@6lMia@D&PDK8)$4}fRfTb*W zjfs?<#{XO*jrb)Ehn=1nx6@;ZbiQtyb%P7nO>=ZqQ;-Ue4)PfnKIwuj2`?ccMq>fI z02bzgawx-?rSJ@vO*J7K20KTLJt0YM0xnrijAt2xF`%NO9ix-Wj>CCm5&B>$%2)H% z6xKvsiweOD;Cz*i1{g#yh({2SfKrz#HK|g|*Q82Kit(C73`1rpEI3`dEx2~REx7hB zx^{*!DMT??d#v1k1soP0U=fzsU)}5Tgt8>Rg1w3WST0`?b-WU0Z%X!Nn0-~U zI*#EEXH0jE3p(^ ztP~f3;tKF;2)u%hj)IT$_f4<=qg_Y;F?$<5d(OZ}o z(v91oXi*8Bh(!IL?)Y@qZqE+7_I)sdDsE?Cyo^s?8i9A8NYR;RfFiW37=|8P@zG6$ zQ_!XC)I`BAvF||I5GsW-Cd-H`6J;~VjzrlJWXGZ`_7#{S$Y(V#%swF6F+>{`l2L^u zvJ62?V`*fwQ8tV0Xp|i#vnui-cQ^v_T>Tl-*4o=>4A{p_izxgq9fk zP?Vf5%yZNNg|pa=OvfM1%V3X*ob&xD-Xo=7~;C@EPBA01)EbFWqLQ_s2hU1 z8Aox3q1a7OVB}`*N!T(83gTEMFycwHXzkH6l5E8fke}3&NsmYe|8*@UsP(9+#ey>b zLh+ChS#Sd*L~#-r5rtz;@!eF2Do@j-yjFa$yusMQ%CfbulI=HZPq5onl~t!y>`)pdvQ3#Mq*o z)>W9GiX?kNGPW;gG?@v=XLL2}Y0hgr6X4HlJT^MZ8qWmyWsS$~=aR-V0sfN4V@veB z#xnu_d5y9WQ%0sgYaWAjwicqYJCH6A;vn#MB$zNYcmX4N&G3Gj7|$KH$654vXp zd|TtOAqzB~3Gji&W0$s}@l1d>>ciIUy2djB{<C@_#4>gX*?6)wYlAn zYzu>xm{hssq(a;?scZlf%uS3VHwGYI2QUf%(E@V4n{vGYWHyarFfSm$g+(`j9na$7 zZAK&TfQVC;?RPxuJMFWr=HTEGo;Rb zO@l-3{=ord^MEE#ndDie7}hDG=w3_Z@Hl7X3Xd`u&p4|crFP-%5jf!LIyhObMl6+_ zIXHt`wGMt7Z@K0cV@HXK@|a%HoXjYCI4K~{<8_L&=S!X9TFW;jI_6N3oXP}|YQjdfKQX;FbEtCoVCBif zmBZ7AaMbG1+O#w6;L%%4jm5+hbv_V7Y(2lH)CVoK8xLo+aFhdIlj8)(qqQJtcYfr+ zfpssabyue37H@}JT}SSa{w zMzEOLw-1ViVntKzdkh!+$@dhHjoyRCQEdEs%ck&a5gh!ioJqr>$Rtl3DZIY|M+xvf zA&yKXaN0CujtiyayhvJ~BuVlRt6e%`uN+C>5y1o=2u$F?!~`BgOyKdt1Rf?#@&Ugj zA3{y?S>Ple15DtN#snTpd~5g*U()e4H2lM@GA3qgMiC7OZzIqoljputiemW3SjGJP zZT4e7sjS8GtokeXoQ9t~Z487(SO-5xD&71y(Ecq(Bb{5>_}_)4`K3So#PJ6oE53RB zrxwq37ruV+_sHWw4NvPFfa|LsphJx2{$p?gPQ6x*&wrd!!!bqoKpW3fd6fedoIZ6s z2Ua~C$!)H89;@K+vfn-+E;4+0=>QHtA27c4KW(6?Fe3pl~bxb*YfA<^+m^Pss%*M%Fa90GxeopB zaood#4%8puT^p91$l*C6eeMFQJkE#IkSl^K?*#FrPyp#zVjd?*im_89Md*X)5JEan z$ncgJdlGRh;>^i;^o(a`*f*YPiB6*Mbc4Qe#nTlY-o+7}$2fqyZanjGH#*yEg4-P4 zJAyC)f5+r4LgB4B>TMIFq)!ZyK8H4V*6E6RK_t0?+Gjw=^W!Ar4I~djC!r4KrFEV$ z@z5*wl6Twqx3g}hV*Q%hrW*yFWA{DaeNlSFTZbXfY4l+RAEq3i=kcYAB^II2pEMz7 zJ=UB5z6?{)r=0jf3%D7Cp6jz#b+Ljrbj6;oWBdcOKLaUd_+32ysv^rdL#Ng$OQ Date: Mon, 23 Jun 2025 20:18:28 +0000 Subject: [PATCH 220/223] Bump versions to 1.2.1 (#333) ## Description of Changes These version bumps were supposed to happen in https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/332, but apparently I messed something up while I was switching branches. ## API - [ ] This is an API breaking change to the SDK No breaking changes ## Requires SpacetimeDB PRs None. ## Testsuite SpacetimeDB branch name: master ## Testing CI only Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- .../csharp/examples~/quickstart-chat/server/StdbModule.csproj | 2 +- .../examples~/regression-tests/server/StdbModule.csproj | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index b3ac109a6ad..5248df62785 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk - 1.2.0 - 1.2.0 + 1.2.1 + 1.2.1 $(DefaultItemExcludes);*~/** packages diff --git a/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj b/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj index f290d226a0d..0513a812181 100644 --- a/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj +++ b/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj @@ -14,7 +14,7 @@ - + diff --git a/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj b/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj index 3284863813a..c6b1cba1f97 100644 --- a/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj +++ b/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj @@ -8,7 +8,7 @@ - + From 4b1cce252710e3605cf8b7559e32245f04ac0cca Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Mon, 23 Jun 2025 23:57:33 +0000 Subject: [PATCH 221/223] Bump Unity package version to 1.2.1 (#334) ## Description of Changes Missed in https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/333. We should update the 1.2.1 tag and the `release/latest` branch after this. ## API - [ ] This is an API breaking change to the SDK Nope ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing CI only Co-authored-by: Zeke Foppa --- sdks/csharp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 619551a053f..78391515eb2 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.2.0", + "version": "1.2.1", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From 6c419ccaa5174eb0d68ab0675130c7b8b9ec5db6 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Wed, 25 Jun 2025 15:57:53 +0000 Subject: [PATCH 222/223] Add `tools~/upgrade-version.py` (#335) ## Description of Changes I'm tired of messing up version updates. I "vibecoded" a script to do it. ## API - [ ] This is an API breaking change to the SDK No. No changes to runtime code. ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing ``` $ python3 tools~/update-version.py 1.1.1 Updated: ./SpacetimeDB.ClientSDK.csproj Updated: ./tests~/tests.csproj Updated: ./examples~/regression-tests/server/StdbModule.csproj Updated: ./examples~/regression-tests/client/client.csproj Updated: ./examples~/quickstart-chat/server/StdbModule.csproj Updated: ./examples~/quickstart-chat/client/client.csproj Updated version in package.json to 1.1.1 $ git diff -U1 diff --git a/SpacetimeDB.ClientSDK.csproj b/SpacetimeDB.ClientSDK.csproj index 5248df6..b3ca7e8 100644 --- a/SpacetimeDB.ClientSDK.csproj +++ b/SpacetimeDB.ClientSDK.csproj @@ -18,4 +18,4 @@ https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk - 1.2.1 - 1.2.1 + 1.1.1 + 1.1.1 $(DefaultItemExcludes);*~/** @@ -27,3 +27,3 @@ - + diff --git a/examples~/quickstart-chat/server/StdbModule.csproj b/examples~/quickstart-chat/server/StdbModule.csproj index 0513a81..f290d22 100644 --- a/examples~/quickstart-chat/server/StdbModule.csproj +++ b/examples~/quickstart-chat/server/StdbModule.csproj @@ -16,3 +16,3 @@ - + diff --git a/examples~/regression-tests/server/StdbModule.csproj b/examples~/regression-tests/server/StdbModule.csproj index c6b1cba..3284863 100644 --- a/examples~/regression-tests/server/StdbModule.csproj +++ b/examples~/regression-tests/server/StdbModule.csproj @@ -10,3 +10,3 @@ - + diff --git a/package.json b/package.json index 7839151..a627246 100644 --- a/package.json +++ b/package.json @@ -3,3 +3,3 @@ "displayName": "SpacetimeDB SDK", - "version": "1.2.1", + "version": "1.1.1", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", ``` --------- Co-authored-by: Zeke Foppa --- sdks/csharp/tools~/upgrade-version.py | 78 +++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 sdks/csharp/tools~/upgrade-version.py diff --git a/sdks/csharp/tools~/upgrade-version.py b/sdks/csharp/tools~/upgrade-version.py new file mode 100644 index 00000000000..95ce86339dc --- /dev/null +++ b/sdks/csharp/tools~/upgrade-version.py @@ -0,0 +1,78 @@ +import os +import re +import sys +import json +import argparse + +def update_csproj_file(path, version): + with open(path, 'r', encoding='utf-8') as f: + lines = f.readlines() + + updated_lines = [] + version_prefix = '.'.join(version.split('.')[:2]) + '.*' + version_tag_written = set() + + for i, line in enumerate(lines): + # Update PackageReference for SpacetimeDB.* + updated_line = re.sub( + r'(]*Include="SpacetimeDB\.[^"]*"[^>]*Version=")[^"]*(")', + rf'\g<1>{version_prefix}\g<2>', + line + ) + + for tag in ('Version', 'AssemblyVersion'): + if re.search(rf'<{tag}>.*', updated_line.strip()): + updated_line = re.sub( + rf'(<{tag}>).*()', + rf'\g<1>{version}\g<2>', + updated_line + ) + version_tag_written.add(tag) + + updated_lines.append(updated_line) + + with open(path, 'w', encoding='utf-8') as f: + f.writelines(updated_lines) + print(f"Updated: {path}") + +def update_all_csproj_files(version): + for root, _, files in os.walk('.'): + for file in files: + if file.endswith('.csproj'): + update_csproj_file(os.path.join(root, file), version) + +def update_package_json(version): + path = 'package.json' + if os.path.exists(path): + with open(path, 'r', encoding='utf-8') as f: + data = json.load(f) + data['version'] = version + with open(path, 'w', encoding='utf-8') as f: + json.dump(data, f, indent=2) + f.write('\n') # ensure trailing newline + print(f"Updated version in {path} to {version}") + else: + print("package.json not found.") + +def main(): + parser = argparse.ArgumentParser( + description='Update version numbers in .csproj files and package.json', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + python upgrade-version.py 1.2.3 + python upgrade-version.py --version 1.2.3 + """ + ) + parser.add_argument( + 'version', + help='Version number to set (e.g., 1.2.3)' + ) + + args = parser.parse_args() + + update_all_csproj_files(args.version) + update_package_json(args.version) + +if __name__ == '__main__': + main() From 533c14bea301c00e0899db57818a2f0eeb43e7b0 Mon Sep 17 00:00:00 2001 From: rekhoff Date: Mon, 7 Jul 2025 14:36:20 +0000 Subject: [PATCH 223/223] Update WebGL message queue to 1.2.1 format (#342) ## Description of Changes This is a fix for community bug https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/340 that was the result of changes to SpacetimeDBClient code that missed changes to the WebGL build. ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs - None ## Testsuite SpacetimeDB branch name: master ## Testing - [X] Tested changes against Blackholio running under a Unity WebGL build --- sdks/csharp/src/SpacetimeDBClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index c19f05b2ed4..1f2785b4124 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -421,7 +421,7 @@ internal void ParseMessages() #if UNITY_WEBGL && !UNITY_EDITOR yield return null; - while (_messageQueue.Count > 0) + while (_parseQueue.Count > 0) #endif try {
    @@ -203,14 +229,32 @@ public void Apply(MultiDictionaryDelta delta, List 0) + if (their.IsValueChange) { - if (ValueComparer.Equals(my.Value, their.Value)) + // Their update expects to change the value associated with this key. + + var (before, after) = their.ValueChange; + Debug.Assert(ValueComparer.Equals(my.Value, before.Value)); + var reducedMultiplicity = (int)my.Multiplicity + before.Delta; + if (reducedMultiplicity != 0) + { + PseudoThrow($"Attempted to apply {their} to {my}, but this resulted in a multiplicity of {reducedMultiplicity}, failing to correctly remove the row before applying the update"); + } + RawDict[key] = (after.Value, (uint)after.Delta); + + wasUpdated.Add((key, my.Value, after.Value)); + } + else + { // !their.IsValueChange + // Their update does not expect to change the value associated with this key. + // However, it may remove the key-value pair entirely. + + var theirDelta = their.NonValueChange; + Debug.Assert(ValueComparer.Equals(my.Value, theirDelta.Value), $"mismatched value change: {my.Value} {theirDelta.Value} {their}"); + var newMultiplicity = (int)my.Multiplicity + theirDelta.Delta; + if (newMultiplicity > 0) { // Update the count, NOT dispatching an update event. @@ -220,50 +264,47 @@ public void Apply(MultiDictionaryDelta delta, List= my.Multiplicity, "Row was not removed enough times in update."); - - // Here, we actually have meaningful changes, so use their value. - RawDict[key] = (their.Value, (uint)newMultiplicity); - wasUpdated.Add((key, my.Value, their.Value)); // store both the old and new values. - } - } - else // if (newMultiplicity <= 0) - { - // This is a removal. - if (newMultiplicity < 0) + else // if (newMultiplicity <= 0) { - PseudoThrow($"Internal error: Removing row with key {key} {-theirDelta} times, but it is only present {my.Multiplicity} times."); + // This is a removal. + if (newMultiplicity < 0) + { + PseudoThrow($"Internal error: Removing row with key {key} {-theirDelta.Delta} times, but it is only present {my.Multiplicity} times."); + } + RawDict.Remove(key); + wasRemoved.Add(new(key, theirDelta.Value)); } - - RawDict.Remove(key); - wasRemoved.Add(new(key, their.Value)); } } else { // Key is not present in map. - if (theirDelta < 0) - { - PseudoThrow($"Internal error: Removing row with key {key} {-theirDelta} times, but it not present."); - } - else if (theirDelta == 0) + if (their.IsValueChange) { - // Hmm. - // This is not actually a problem. - // Do nothing. + PseudoThrow($"Internal error: Can't perform a value change on a nonexistent key {key} (change: {their})."); } - else if (theirDelta > 0) + else { - RawDict[key] = (their.Value, (uint)theirDelta); - wasInserted.Add(new(key, their.Value)); + var theirDelta = their.NonValueChange; + + if (theirDelta.Delta == 0) + { + // Hmm. + // This is not actually a problem. + // Do nothing. + } + else if (theirDelta.Delta < 0) + { + PseudoThrow($"Internal error: Can't remove nonexistent key {theirDelta.Value}"); + } + else + { + RawDict[key] = (theirDelta.Value, (uint)theirDelta.Delta); + wasInserted.Add(new(key, theirDelta.Value)); + } } } } - - } /// @@ -293,10 +334,13 @@ public override string ToString() /// /// A bulk change to a multidictionary. Allows both adding and removing rows. /// + /// You MUST use the MultiDictionaryDelta(IEqualityComparer keyComparer, IEqualityComparer valueComparer) + /// to construct this -- it is a struct for performance reasons, but the default constructor creates an invalid collection! + /// /// Can be applied to a multidictionary, and also inspected before application to see /// what rows will be deleted. (This is used for OnBeforeDelete.) /// - /// Curiously, the order of operations applied to a MultiDictionaryDelta does not matter. + /// The order of operations applied to a MultiDictionaryDelta does not matter. /// No matter the order of Add and Remove calls on a delta, when the Delta is applied, /// the result will be the same, as long as the Add and Remove *counts* for each KeyValuePair are /// the same. @@ -304,10 +348,14 @@ public override string ToString() /// (MultiDictionary would also be "conflict-free" if it didn't support Remove.) /// /// The delta may include value updates. - /// A value can be updated multiple times, but each update must set the result to the same value. - /// When applying a delta, if the target multidictionary has multiple copies of (key, value) pair, - /// the row must be removed exactly the correct number of times. It can be inserted an arbitrary number of times. + /// When applied, the delta must maintain the invariant of MultiDictionary that each key maps to exactly one value. + /// For example, if the target dictionary has the state: + /// (k1: v1) (k1: v1) + /// Then a delta must remove both of these key-value pairs if it wishes to assign a new value to k1. /// + /// Each key can be associated with at most two values in a MultiDictionaryDelta. + /// For example, -(k1: v1) +(k1: v2) -(k1: v2) +(k1: v3) is NOT a valid MultiDictionaryDelta. + /// /// When removing a row for an update, it is legal for the passed value to be equal to EITHER the old value or the new value. /// (This is because I'm not sure what SpacetimeDB core does.) /// @@ -316,19 +364,262 @@ public override string ToString() internal struct MultiDictionaryDelta : IEquatable> { /// - /// For each key, track its NEW value (or old value, but only if we have never seen the new value). - /// Also track the number of times it has been removed and inserted. - /// We keep these separate so that we can debug-assert that a KVP has been removed enough times (in case - /// there are multiple copies of the KVP in the map we get applied to.) + /// A change to an individual value associated to a key. + /// + public struct ValueDelta + { + /// + /// The value stored. + /// + public TValue Value; + + /// + /// The change in multiplicity of the value. + /// + public int Delta; + + public ValueDelta(TValue Value, int Delta) + { + this.Value = Value; + this.Delta = Delta; + } + + public override string ToString() + { + return $"{Value} x ({Delta})"; + } + + public bool Equals(ValueDelta other, IEqualityComparer equalityComparer) => + equalityComparer.Equals(Value, other.Value) && Delta == other.Delta; + } + + /// + /// A change to a key-value pair. + /// + /// - If the value associated to the key does not change, then .IsValueChange == false; + /// the key-value pair can only have multiplicity changes. + /// Use .NonValueChange to get at this multiplicity information. + /// + /// - If the value associated to the key does change, then .IsValueChange == true; + /// use .ValueChange to get the values before and after the change, together with multiplicity information. + /// + public struct KeyDelta + { + // The (one | two) ValueDeltas associated with this key. + // + // You can think of this struct as a HashSet with signed multiplicities that stores at most two values. + // + // While we are accumulating changes to this key, we don't know which of the values we've + // seen so far is the old value, and which is the new value. + // (We can't look incoming values up in the existing dictionary for thread-safety reasons.) + // + // Once all changes are accumulated, we expect either: + // - There is only one value (NonValueChange) + // - There are two values: + // - One with (-), one with (+) delta (ValueChange) + // - One with 0, one with non-0 delta (This is odd, but we treat it as NonValueChange.) + // - Both with the same delta sign. This represents an unrecoverable error, so we throw an exception. + // + // Invariant: If D2 is present, its (signed) Delta should be >= the Delta for D1. + // This is enforced by the Normalize method, which should be called after + // any other method that modifies this struct. This ensures that D1 holds the old value, + // and D2 holds the new value. But this guarantee is only present after all changes have been accumulated. + ValueDelta D1; + ValueDelta? D2; + + private void Normalize() + { + if (D2 != null && D2.Value.Delta < D1.Delta) + { + var tmp = D2.Value; + D2 = D1; + D1 = tmp; + } + } + + /// + /// Construct a KeyDelta from a single ValueDelta. + /// + /// + public KeyDelta(ValueDelta delta) + { + D1 = delta; + D2 = null; + } + + /// + /// If this KeyDelta is a value change -- that is, it removes one value some number of times and adds another some number of times. + /// (If it isn't a value change, it just will consist of adds or removes for a single value). + /// + public bool IsValueChange + { + get => D2 != null && D1.Delta < 0 && D2.Value.Delta > 0; + } + + /// + /// The deltas in the case of this KeyDelta being a value change. + /// Guarantees Before.Delta < 0 && After.Delta > 0. + /// + public (ValueDelta Before, ValueDelta After) ValueChange + { + get + { + if (!IsValueChange) + { + throw new InvalidOperationException($"KeyDelta {this} is not a ValueChange"); + } + return (D1, D2!.Value); + } + } + + /// + /// If !IsUpdate, this gives you the single relevant ValueDelta for this key. + /// + public ValueDelta NonValueChange + { + get + { + if (IsValueChange) + { + throw new Exception($"KeyDelta {this} is a ValueChange"); + } + + if (D2 == null) + { + return D1; + } + else + { + // Now we're in a weird place. + // We're not an update, but D2 is initialized. + // This means that at least one of D1 or D2 has Delta == 0. + // If exactly one of them has Delta == 0, we're okay: + if (D1.Delta == 0 && D2.Value.Delta != 0) + { + return D2.Value; + } + else if (D1.Delta != 0 && D2.Value.Delta == 0) + { + return D1; + } + else + { + // In this case, something strange is going on: both values have the same sign. + // There's nothing sensible to do here, and this represents a server-side error, so just throw. + throw new InvalidOperationException($"Called NonValueChange on a ValueDelta in an ambiguous state: {this}"); + } + } + } + } + + /// + /// Add a copy of this Value to this KeyDelta. + /// + /// + /// + public void Add(TValue value, IEqualityComparer equalityComparer) + { + if (equalityComparer.Equals(value, D1.Value)) + { + D1.Delta += 1; + } + else if (D2 == null) + { + D2 = new(value, +1); + } + else + { + var d2 = D2.Value; + Debug.Assert(equalityComparer.Equals(value, d2.Value)); + // In release mode, the above assert won't fire. + // This means that if we get more than two values, the first two distinct values seen + // will be the ones stored in the KeyDelta. + d2.Delta += 1; + D2 = d2; + } + Normalize(); + } + + /// + /// Remove a copy of this Value from this KeyDelta. + /// + /// + /// + public void Remove(TValue value, IEqualityComparer equalityComparer) + { + if (equalityComparer.Equals(value, D1.Value)) + { + D1.Delta -= 1; + } + else if (D2 == null) + { + D2 = new(value, -1); + } + else + { + var newD2 = D2.Value; + Debug.Assert(equalityComparer.Equals(value, newD2.Value)); + // In release mode, the above assert won't fire. + // This means that if we get more than two values, the first two distinct values seen + // will be the ones stored in the KeyDelta. + newD2.Delta -= 1; + D2 = newD2; + } + Normalize(); + } + + /// + /// Check if two KeyDeltas are equal. + /// + /// If either is in an invalid state, this throws. + /// That means you should avoid comparing KeyDeltas + /// (and therefore MultiDictionaryDeltas) unless you are sure they are valid, i.e. until they have + /// absorbed all the necessary Adds and Removes. + /// + /// + /// + /// + public bool Equals(KeyDelta other, IEqualityComparer equalityComparer) + { + if (IsValueChange != other.IsValueChange) return false; + if (IsValueChange) + { + var asUpdate = ValueChange; + var otherAsUpdate = other.ValueChange; + return asUpdate.Before.Equals(otherAsUpdate.Before, equalityComparer) && + asUpdate.After.Equals(otherAsUpdate.After, equalityComparer); + } + else + { + return NonValueChange.Equals(other.NonValueChange, equalityComparer); + } + } + + public override string ToString() + { + if (D2 == null) + { + return D1.ToString(); + } + else + { + return $"({D1}, {D2})"; + } + } + } + + /// + /// For each key, track its value (or its old and new values). + /// Also track the deltas associated to the values for this key. /// - readonly Dictionary RawDict; + readonly Dictionary RawDict; readonly IEqualityComparer ValueComparer; /// /// Construct a MultiDictionaryDelta. /// - /// This is the only valid constructor for a MultiDictionaryDelta - using the parameterless constructor + /// This is the ONLY valid constructor for a MultiDictionaryDelta - using the parameterless constructor /// will result in null pointer errors. But we can't enforce this because of Unity. /// /// @@ -353,20 +644,16 @@ public void Add(TKey key, TValue value) } Debug.Assert(RawDict != null); Debug.Assert(key != null); - if (RawDict.TryGetValue(key, out var result)) + KeyDelta result; + if (RawDict.TryGetValue(key, out result)) { - if (result.Inserts > 0) - { - Debug.Assert(ValueComparer.Equals(value, result.Value), "Added key-value pair with mismatched value to existing data"); - } - // Now, make sure we override the value, since it may have been added in a remove, which MAY have passed the - // out-of-date value. - RawDict[key] = (value, result.Removes, result.Inserts + 1); + result.Add(value, ValueComparer); } else { - RawDict[key] = (value, 0, 1); + result = new(new(value, +1)); } + RawDict[key] = result; } /// @@ -383,15 +670,16 @@ public void Clear() /// public void Remove(TKey key, TValue value) { - if (RawDict.TryGetValue(key, out var result)) + KeyDelta result; + if (RawDict.TryGetValue(key, out result)) { - // DON'T assert that result.Value == value: if an update is happening, that may not be the case. - RawDict[key] = (result.Value, result.Removes + 1, result.Inserts); + result.Remove(value, ValueComparer); } else { - RawDict[key] = (value, 1, 0); + result = new(new(value, -1)); } + RawDict[key] = result; } public override string ToString() @@ -400,7 +688,7 @@ public override string ToString() result.Append("SpacetimeDB.MultiDictionaryDelta { "); foreach (var item in RawDict) { - result.Append($"({item.Key}: {item.Value.Value}) x (+{item.Value.Inserts} -{item.Value.Removes}), "); + result.Append($"({item.Key}: {item.Value}, "); } result.Append("}"); return result.ToString(); @@ -413,17 +701,21 @@ public bool Equals(MultiDictionaryDelta other) var (key, my) = item; if (other.RawDict.TryGetValue(key, out var their)) { - if (!(ValueComparer.Equals(my.Value, their.Value) && my.Inserts == their.Inserts && my.Removes == their.Removes)) + if (!their.Equals(my, ValueComparer)) { return false; } } + else + { + return false; + } } return true; } - public readonly IEnumerable> Entries + public readonly IEnumerable> Entries { get { diff --git a/sdks/csharp/tests~/MultiDictionaryTests.cs b/sdks/csharp/tests~/MultiDictionaryTests.cs index 0012c9c7445..3a2d34177d3 100644 --- a/sdks/csharp/tests~/MultiDictionaryTests.cs +++ b/sdks/csharp/tests~/MultiDictionaryTests.cs @@ -19,22 +19,35 @@ Gen>> ListWithNormalizedDuplicates where TKey : notnull { return Gen.Select(g1, g2, (b1, b2) => new KeyValuePair(b1, b2)).List[ListMinLength, ListMaxLength].Select(list => + NormalizeDuplicates(list, equality) + ); + } + + /// + /// Normalize a list so that, if any two items have duplicate Keys, they have the same Value. + /// + /// + /// + /// + /// + /// + List> NormalizeDuplicates(List> list, IEqualityComparer equality) + where TKey : notnull + { + Dictionary seenKeys = new(equality); + for (var i = 0; i < list.Count; i++) { - Dictionary seenKeys = new(equality); - for (var i = 0; i < list.Count; i++) + var (b1, b2) = list[i]; + if (seenKeys.ContainsKey(b1)) { - var (b1, b2) = list[i]; - if (seenKeys.ContainsKey(b1)) - { - list[i] = new(b1, seenKeys[b1]); - } - else - { - seenKeys[b1] = b2; - } + list[i] = new(b1, seenKeys[b1]); } - return list; - }); + else + { + seenKeys[b1] = b2; + } + } + return list; } [Fact] @@ -153,8 +166,11 @@ public void ChunkedRemovals() Gen.Select(ListWithRemovals(Gen.Byte[1, 10], Gen.Byte[1, 10], EqualityComparer.Default, maxLength), Gen.Int[0, 32].List[0, 5]).Sample((listRemovals, cuts) => { // Test that building up a MultiDictionary an operation-at-a-time is the same as randomly grouping the operations and applying them in chunks using MultiDictionaryDeltas. + // Pre-normalizes the list of operations so that the same key is always associated with the same value. + // Note: When looking at test failures for this test, keep in mind we do some post-processing of the sample input data. - // So the listed `removals` and `cuts` may be changed slightly during the test. + // So the listed operations may be changed slightly while the test is executing. + // CsCheck doesn't give us a good way to log this :/ var (list, removals) = listRemovals; cuts.Add(0); cuts.Add(maxLength); @@ -173,8 +189,6 @@ public void ChunkedRemovals() { var delta = new MultiDictionaryDelta(EqualityComparer.Default, EqualityComparer.Default); - var (start_, end_) = (int.Min(start, list.Count), int.Min(end, list.Count)); - foreach (var (item, remove) in list[start..end].Zip(removals[start..end])) { // it's an error to remove-too-many-times with the Delta api. @@ -217,6 +231,115 @@ public void ChunkedRemovals() }, iter: 10_000); } + [Fact] + public void ChunkedRemovalsWithValueChanges() + { + // Test that building up a MultiDictionary an operation-at-a-time is the same as randomly grouping the operations and applying them in chunks using MultiDictionaryDeltas. + // Unlike ChunkedRemovals, this doesn't pre-normalize the list of operations so that the same key always has the same value. + // Instead, in a particular chunk of operations, if a new value is assigned to a key, we go in and remove the old value the correct number of times. + + var maxLength = 32; + // Don't pre-normalize the list. + // We want to normalize per-chunk instead. + var listRemovalsNonNormalized = Gen.SelectMany( + Gen.Int[0, maxLength], (listLength) => Gen.Select( + // the data itself + Gen.Select(Gen.Byte[1, 10], Gen.Byte[1, 10], (b1, b2) => new KeyValuePair(b1, b2)).List[listLength, listLength], + // whether this element should be added or removed + Gen.Bool.List[listLength] + )); + + Gen.Select(listRemovalsNonNormalized, Gen.Int[0, maxLength].List[0, 5]).Select((listRemovals, cuts) => + { + var (list, removals) = listRemovals; + + cuts.Add(0); + cuts.Add(maxLength); + cuts = cuts.Select(cut => int.Min(cut, list.Count)).ToList(); + cuts.Sort(); + + var listWithRemovals = list.Zip(removals).ToList(); + + var equalityComparer = EqualityComparer.Default; + + var viaAddRemove = new MultiDictionary(equalityComparer, equalityComparer); + + return cuts.Zip(cuts.Skip(1)).Select((range) => + { + var (start, end) = range; + var listChunk = list[start..end]; + NormalizeDuplicates(listChunk, equalityComparer); + var removalsChunk = removals[start..end]; + + return (listChunk, removalsChunk); + }).ToList(); + }) + .Sample((chunkedListRemovals) => + { + var equalityComparer = EqualityComparer.Default; + + var viaAddRemove = new MultiDictionary(equalityComparer, equalityComparer); + var viaChunkDeltas = new MultiDictionary(equalityComparer, equalityComparer); + + foreach (var (listChunk, removalsChunk) in chunkedListRemovals) + { + var delta = new MultiDictionaryDelta(equalityComparer, equalityComparer); + + foreach (var (item, remove) in listChunk.Zip(removalsChunk)) + { + if (viaAddRemove.Multiplicity(item.Key) > 0 && !equalityComparer.Equals(viaAddRemove[item.Key], item.Value)) + { + var oldValue = viaAddRemove[item.Key]; + // This chunk is going to change the value associated with this key. + // Remove it the correct number of times. + var mult = viaAddRemove.Multiplicity(item.Key); + for (uint i = 0; i < mult; i++) + { + viaAddRemove.Remove(item.Key, out var _); + delta.Remove(item.Key, oldValue); + } + } + + // it's an error to remove-too-many-times with the Delta api. + // so, don't remove anything we don't have. + var remove_ = remove && viaAddRemove.Contains(item); + if (remove_) + { + viaAddRemove.Remove(item.Key, out var _); + delta.Remove(item.Key, item.Value); + } + else + { + viaAddRemove.Add(item.Key, item.Value); + delta.Add(item.Key, item.Value); + } + } + foreach (var (key, value) in viaChunkDeltas.WillRemove(delta)) + { + Assert.True(viaChunkDeltas.Contains(new(key, value))); + } + var wasInserted = new List>(); + var wasMaybeUpdated = new List<(byte key, byte oldValue, byte newValue)>(); + var wasRemoved = new List>(); + + viaChunkDeltas.Apply(delta, wasInserted, wasMaybeUpdated, wasRemoved); + foreach (var (key, value) in wasInserted) + { + Assert.True(viaChunkDeltas.Contains(new(key, value))); + } + foreach (var (key, oldValue, newValue) in wasMaybeUpdated) + { + Assert.True(viaChunkDeltas.Contains(new(key, newValue))); + } + foreach (var (key, value) in wasRemoved) + { + Assert.False(viaChunkDeltas.Contains(new(key, value))); + } + Assert.Equal(viaAddRemove, viaChunkDeltas); + } + }, iter: 10_000); + } + [Fact] public void IdentitiesWorkAsPrimaryKeys() { @@ -241,4 +364,44 @@ public void IdentitiesWorkAsPrimaryKeys() var wasRemoved = new List>(); dict.Apply(delta, wasInserted, wasMaybeUpdated, wasRemoved); } + + [Fact] + public void InsertThenDeleteOfOldRow() + { + var dict = new MultiDictionary(EqualityComparer.Default, EqualityComparer.Default); + dict.Add(1, 2); + + var delta = new MultiDictionaryDelta(EqualityComparer.Default, EqualityComparer.Default); + delta.Add(1, 2); + delta.Add(1, 3); + delta.Remove(1, 2); + delta.Remove(1, 2); + + var wasInserted = new List>(); + var wasMaybeUpdated = new List<(byte key, byte oldValue, byte newValue)>(); + var wasRemoved = new List>(); + dict.Apply(delta, wasInserted, wasMaybeUpdated, wasRemoved); +#pragma warning disable xUnit2017 + Assert.True(wasMaybeUpdated.Contains((1, 2, 3)), $"{dict}: {wasMaybeUpdated}"); +#pragma warning restore xUnit2017 + + // And one more permutation. + + dict = new MultiDictionary(EqualityComparer.Default, EqualityComparer.Default); + dict.Add(1, 2); + + delta = new MultiDictionaryDelta(EqualityComparer.Default, EqualityComparer.Default); + delta.Add(1, 3); + delta.Remove(1, 2); + delta.Remove(1, 2); + delta.Add(1, 2); + + wasInserted = new List>(); + wasMaybeUpdated = new List<(byte key, byte oldValue, byte newValue)>(); + wasRemoved = new List>(); + dict.Apply(delta, wasInserted, wasMaybeUpdated, wasRemoved); +#pragma warning disable xUnit2017 + Assert.True(wasMaybeUpdated.Contains((1, 2, 3)), $"{dict}: {wasMaybeUpdated}"); +#pragma warning restore xUnit2017 + } } \ No newline at end of file From ce7828e4fe5cf2755a2eded13e5895e5977bbcb2 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 22 Apr 2025 12:01:57 -0700 Subject: [PATCH 199/223] Bump versions to 1.1.1 (#297) ## Description of Changes Just bumping version numbers in preparation for an upcoming release. I also relaxed the version constraints in the `.csproj` files to be flexible in their patch versions. ## API - [ ] This is an API breaking change to the SDK No breaking changes. ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing Just existing CI, since this just bumps version numbers. Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- .../csharp/examples~/quickstart-chat/server/StdbModule.csproj | 2 +- .../examples~/regression-tests/server/StdbModule.csproj | 2 +- sdks/csharp/package.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index e55d9df374f..b3ca7e8e206 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -16,8 +16,8 @@ logo.png README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk - 1.1.0 - 1.1.0 + 1.1.1 + 1.1.1 $(DefaultItemExcludes);*~/** packages diff --git a/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj b/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj index 07c9f725689..f290d226a0d 100644 --- a/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj +++ b/sdks/csharp/examples~/quickstart-chat/server/StdbModule.csproj @@ -14,7 +14,7 @@ - + diff --git a/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj b/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj index 479928b1fc9..3284863813a 100644 --- a/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj +++ b/sdks/csharp/examples~/regression-tests/server/StdbModule.csproj @@ -8,7 +8,7 @@ - + diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index 45c142a21a1..a627246adc9 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.1.0", + "version": "1.1.1", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From 0fa4cf9da1e2bf2fe758f97d8abf37a8b54cbf3e Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 22 Apr 2025 12:12:33 -0700 Subject: [PATCH 200/223] CI - Release branch check auto-changes base branch (#298) ## Description of Changes Instead of our CI failing and telling the user that a PR should be based on `master`, we automatically change the base branch to `master`. ## API No code changes. ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing - [x] See below, where the new CI changed the base branch of this PR! - [x] On this test PR, the base branch was not changed: https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/299 --------- Co-authored-by: Zeke Foppa --- .../.github/workflows/check-pr-base.yml | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/sdks/csharp/.github/workflows/check-pr-base.yml b/sdks/csharp/.github/workflows/check-pr-base.yml index e3c164863d3..0f401c5bc96 100644 --- a/sdks/csharp/.github/workflows/check-pr-base.yml +++ b/sdks/csharp/.github/workflows/check-pr-base.yml @@ -3,20 +3,29 @@ name: Git tree checks on: pull_request: types: [opened, edited, reopened, synchronize] - merge_group: -permissions: read-all + +permissions: + pull-requests: write + contents: read jobs: check_base_ref: name: Release branch restriction runs-on: ubuntu-latest steps: - - id: not_based_on_master + - name: Change base to master if needed if: | github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'release/latest' && ! startsWith(github.event.pull_request.head.ref, 'release/') + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - echo 'Only `release/*` branches are allowed to merge into the release branch `release/latest`.' - echo 'Maybe you want to change your PR base to `master`?' - exit 1 + echo 'Updating PR '"#${{ github.event.pull_request.number }}"' to use base `master`' + echo 'If you do want to release your changes directly by merging into `release/latest`, your branch must start with `release/`.' + + curl -X PATCH \ + -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github+json" \ + https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }} \ + -d '{"base": "master"}' From 20ed2dc067e83e0a00eff544142572a2e92fbfcb Mon Sep 17 00:00:00 2001 From: Daniel Kierkegaard Andersen Date: Tue, 22 Apr 2025 21:59:23 +0200 Subject: [PATCH 201/223] SpacetimeDB working in Unity WebGL Builds (#286) ## Description of Changes As it stands today, Unity WebGL doesn't work. Partially the reason for this is Multi-Threading, and the other reason is the use of `ClientWebSocket`. In order to fix this (specifically in the case of Unity), here's some changes that _can_ be made. Note that this is mostly a suggestion and does come with a few flaws, though arguably it might still be better than it not working at all? Up to you! The Tl;Dr of how it works, is to: - **MultiThreading Problem**: simply invoke the `Task.Run` functions on main thread instead, and use a coroutine in place of where the two simultaneous threads was expected. - **ClientWebSocket**: Use a `.jslib` to create the WebSocket directly within Javascript, and then have JS call the corresponding correct functions. DISCLAIMER: currently OnClose doesn't quite work correctly as `__allocate` isn't invoked correctly. ## API Not a breaking change to the API, should be internal implementation details ## Requires SpacetimeDB PRs None ## Testsuite ???? SpacetimeDB branch name: master ## Testing Open the Blackholeio project, try building it for WebGL - [X] Made a game using the feature: https://daxode.itch.io/eat-to-the-deep --------- Co-authored-by: rekhoff Co-authored-by: John Detter Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> Co-authored-by: James Gilles --- sdks/csharp/src/Plugins.meta | 3 + sdks/csharp/src/Plugins/WebSocket.jslib | 97 +++++++++++ sdks/csharp/src/Plugins/WebSocket.jslib.meta | 3 + sdks/csharp/src/SpacetimeDBClient.cs | 39 ++++- sdks/csharp/src/WebSocket.cs | 174 ++++++++++++++++++- 5 files changed, 312 insertions(+), 4 deletions(-) create mode 100644 sdks/csharp/src/Plugins.meta create mode 100644 sdks/csharp/src/Plugins/WebSocket.jslib create mode 100644 sdks/csharp/src/Plugins/WebSocket.jslib.meta diff --git a/sdks/csharp/src/Plugins.meta b/sdks/csharp/src/Plugins.meta new file mode 100644 index 00000000000..46dd3d9fff0 --- /dev/null +++ b/sdks/csharp/src/Plugins.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0371f6f46d9b423da86a9f6227004906 +timeCreated: 1743867379 \ No newline at end of file diff --git a/sdks/csharp/src/Plugins/WebSocket.jslib b/sdks/csharp/src/Plugins/WebSocket.jslib new file mode 100644 index 00000000000..5fa7605ef47 --- /dev/null +++ b/sdks/csharp/src/Plugins/WebSocket.jslib @@ -0,0 +1,97 @@ +mergeInto(LibraryManager.library, { + WebSocket_Init: function(openCallback, messageCallback, closeCallback, errorCallback) { + this._webSocketManager = { + instances: {}, + nextId: 1, + callbacks: { + open: null, + message: null, + close: null, + error: null + } + }; + + var manager = this._webSocketManager; + manager.callbacks.open = openCallback; + manager.callbacks.message = messageCallback; + manager.callbacks.close = closeCallback; + manager.callbacks.error = errorCallback; + }, + + WebSocket_Connect: function(uriPtr, protocolPtr, authTokenPtr) { + try { + var manager = this._webSocketManager; + var uri = UTF8ToString(uriPtr); + var protocol = UTF8ToString(protocolPtr); + var authToken = UTF8ToString(authTokenPtr); + + var socket = new window.WebSocket(uri, protocol); + socket.binaryType = "arraybuffer"; + + var socketId = manager.nextId++; + manager.instances[socketId] = socket; + + socket.onopen = function() { + if (manager.callbacks.open) { + dynCall('vi', manager.callbacks.open, [socketId]); + } + }; + + socket.onmessage = function(event) { + if (manager.callbacks.message && event.data instanceof ArrayBuffer) { + var buffer = _malloc(event.data.byteLength); + HEAPU8.set(new Uint8Array(event.data), buffer); + dynCall('viii', manager.callbacks.message, [socketId, buffer, event.data.byteLength]); + _free(buffer); + } + }; + socket.onclose = function(event) { + if (manager.callbacks.close) { + var reasonStr = event.reason || ""; + var reasonArray = intArrayFromString(reasonStr); + var reasonPtr = _malloc(reasonArray.length); + HEAP8.set(reasonArray, reasonPtr); + dynCall('viii', manager.callbacks.close, [socketId, event.code, reasonPtr]); + _free(reasonPtr); + } + delete manager.instances[socketId]; + }; + + socket.onerror = function(error) { + if (manager.callbacks.error) { + dynCall('vi', manager.callbacks.error, [socketId]); + } + }; + + return socketId; + } catch (e) { + console.error("WebSocket connection error:", e); + return -1; + } + }, + + WebSocket_Send: function(socketId, dataPtr, length) { + var manager = this._webSocketManager; + var socket = manager.instances[socketId]; + if (!socket || socket.readyState !== socket.OPEN) return -1; + + try { + var data = new Uint8Array(HEAPU8.buffer, dataPtr, length); + socket.send(data); + return 0; + } catch (e) { + console.error("WebSocket send error:", e); + return -1; + } + }, + + WebSocket_Close: function(socketId, code, reasonPtr) { + var manager = this._webSocketManager; + var socket = manager.instances[socketId]; + if (!socket) return; + + var reason = UTF8ToString(reasonPtr); + socket.close(code, reason); + delete manager.instances[socketId]; + } +}); \ No newline at end of file diff --git a/sdks/csharp/src/Plugins/WebSocket.jslib.meta b/sdks/csharp/src/Plugins/WebSocket.jslib.meta new file mode 100644 index 00000000000..5d74094d6e0 --- /dev/null +++ b/sdks/csharp/src/Plugins/WebSocket.jslib.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9c18aedd3a704a7e81f803d770519c0d +timeCreated: 1743867400 \ No newline at end of file diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index ec780134bcc..e9649b94358 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -188,10 +189,18 @@ protected DbConnectionBase() SpacetimeDBNetworkManager._instance.RemoveConnection(this); } }; + +#if UNITY_WEBGL && !UNITY_EDITOR + if (SpacetimeDBNetworkManager._instance != null) + SpacetimeDBNetworkManager._instance.StartCoroutine(PreProcessMessages()); +#endif #endif +#if !(UNITY_WEBGL && !UNITY_EDITOR) + // For targets other than webgl we start a thread to pre-process messages networkMessageProcessThread = new Thread(PreProcessMessages); networkMessageProcessThread.Start(); +#endif } struct UnprocessedMessage @@ -351,10 +360,19 @@ private static IEnumerable BsatnRowListIter(BsatnRowList list) }; } +#if UNITY_WEBGL && !UNITY_EDITOR + IEnumerator PreProcessMessages() +#else void PreProcessMessages() +#endif { while (!isClosing) { + +#if UNITY_WEBGL && !UNITY_EDITOR + yield return null; + while (_messageQueue.Count > 0) +#endif try { var message = _messageQueue.Take(_preProcessCancellationToken); @@ -363,7 +381,11 @@ void PreProcessMessages() } catch (OperationCanceledException) { +#if UNITY_WEBGL && !UNITY_EDITOR + break; +#else return; // Normal shutdown +#endif } } @@ -586,7 +608,13 @@ public void Disconnect() { isClosing = true; connectionClosed = true; - webSocket.Close(); + + // Only try to close if the connection is active + if (webSocket.IsConnected) + { + webSocket.Close(); + } + _preProcessCancellationTokenSource.Cancel(); } @@ -612,7 +640,11 @@ void IDbConnection.Connect(string? token, string uri, string addressOrName, Comp Log.Info($"SpacetimeDBClient: Connecting to {uri} {addressOrName}"); if (!IsTesting) { +#if UNITY_WEBGL && !UNITY_EDITOR + async Task Function() +#else Task.Run(async () => +#endif { try { @@ -628,7 +660,12 @@ void IDbConnection.Connect(string? token, string uri, string addressOrName, Comp Log.Exception(e); } +#if UNITY_WEBGL && !UNITY_EDITOR + } + _ = Function(); +#else }); +#endif } } diff --git a/sdks/csharp/src/WebSocket.cs b/sdks/csharp/src/WebSocket.cs index 8dc4da28da3..71020bb7728 100644 --- a/sdks/csharp/src/WebSocket.cs +++ b/sdks/csharp/src/WebSocket.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.Sockets; using System.Net.WebSockets; +using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -41,6 +42,9 @@ public struct ConnectOptions public WebSocket(ConnectOptions options) { _options = options; +#if UNITY_WEBGL && !UNITY_EDITOR + InitializeWebGL(); +#endif } public event OpenEventHandler? OnConnect; @@ -49,10 +53,111 @@ public WebSocket(ConnectOptions options) public event MessageEventHandler? OnMessage; public event CloseEventHandler? OnClose; +#if UNITY_WEBGL && !UNITY_EDITOR + private bool _isConnected = false; + private bool _isConnecting = false; + public bool IsConnected => _isConnected; +#else public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } +#endif + +#if UNITY_WEBGL && !UNITY_EDITOR +[DllImport("__Internal")] + private static extern void WebSocket_Init( + IntPtr openCallback, + IntPtr messageCallback, + IntPtr closeCallback, + IntPtr errorCallback + ); + + [DllImport("__Internal")] + private static extern int WebSocket_Connect(string uri, string protocol, string authToken); + + [DllImport("__Internal")] + private static extern int WebSocket_Send(int socketId, byte[] data, int length); + + [DllImport("__Internal")] + private static extern void WebSocket_Close(int socketId, int code, string reason); + + [AOT.MonoPInvokeCallback(typeof(Action))] + private static void WebGLOnOpen(int socketId) + { + Instance?.HandleWebGLOpen(socketId); + } + + [AOT.MonoPInvokeCallback(typeof(Action))] + private static void WebGLOnMessage(int socketId, IntPtr dataPtr, int length) + { + try { + byte[] data = new byte[length]; + Marshal.Copy(dataPtr, data, 0, length); + Instance?.HandleWebGLMessage(socketId, data); + } catch (Exception e) { + UnityEngine.Debug.LogError($"Error handling message: {e}"); + } + } + + [AOT.MonoPInvokeCallback(typeof(Action))] + private static void WebGLOnClose(int socketId, int code, IntPtr reasonPtr) + { + try { + string reason = Marshal.PtrToStringUTF8(reasonPtr); + Instance?.HandleWebGLClose(socketId, code, reason); + } catch (Exception e) { + UnityEngine.Debug.LogError($"Error handling close: {e}"); + } + } + + [AOT.MonoPInvokeCallback(typeof(Action))] + private static void WebGLOnError(int socketId) + { + Instance?.HandleWebGLError(socketId); + } + + private static WebSocket Instance; + private int _webglSocketId = -1; + + private void InitializeWebGL() + { + Instance = this; + // Convert callbacks to function pointers + var openPtr = Marshal.GetFunctionPointerForDelegate((Action)WebGLOnOpen); + var messagePtr = Marshal.GetFunctionPointerForDelegate((Action)WebGLOnMessage); + var closePtr = Marshal.GetFunctionPointerForDelegate((Action)WebGLOnClose); + var errorPtr = Marshal.GetFunctionPointerForDelegate((Action)WebGLOnError); + + WebSocket_Init(openPtr, messagePtr, closePtr, errorPtr); + } +#endif public async Task Connect(string? auth, string host, string nameOrAddress, ConnectionId connectionId, Compression compression, bool light) { +#if UNITY_WEBGL && !UNITY_EDITOR + if (_isConnecting || _isConnected) return; + + _isConnecting = true; + try + { + var uri = $"{host}/v1/database/{nameOrAddress}/subscribe?connection_id={connectionId}&compression={compression}"; + if (light) uri += "&light=true"; + + _webglSocketId = WebSocket_Connect(uri, _options.Protocol, auth); + if (_webglSocketId == -1) + { + dispatchQueue.Enqueue(() => OnConnectError?.Invoke( + new Exception("Failed to connect WebSocket"))); + } + } + catch (Exception e) + { + dispatchQueue.Enqueue(() => OnConnectError?.Invoke(e)); + } + finally + { + _isConnecting = false; + } + // Events will be handled via UnitySendMessage callbacks +#else var uri = $"{host}/v1/database/{nameOrAddress}/subscribe?connection_id={connectionId}&compression={compression}"; if (light) { @@ -241,12 +346,23 @@ await Ws.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, return; } } +#endif } public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure) { - Ws?.CloseAsync(code, "Disconnecting normally.", CancellationToken.None); - +#if UNITY_WEBGL && !UNITY_EDITOR + if (_isConnected && _webglSocketId >= 0) + { + WebSocket_Close(_webglSocketId, (int)code, "Disconnecting normally."); + _isConnected = false; + } +#else + if (Ws?.State == WebSocketState.Open) + { + return Ws.CloseAsync(code, "Disconnecting normally.", CancellationToken.None); + } +#endif return Task.CompletedTask; } @@ -261,14 +377,27 @@ public Task Close(WebSocketCloseStatus code = WebSocketCloseStatus.NormalClosure /// The message to send public void Send(ClientMessage message) { +#if UNITY_WEBGL && !UNITY_EDITOR + try + { + var messageBSATN = new ClientMessage.BSATN(); + var encodedMessage = IStructuralReadWrite.ToBytes(messageBSATN, message); + WebSocket_Send(_webglSocketId, encodedMessage, encodedMessage.Length); + } + catch (Exception e) + { + UnityEngine.Debug.LogError($"WebSocket send error: {e}"); + dispatchQueue.Enqueue(() => OnSendError?.Invoke(e)); + } +#else lock (messageSendQueue) { messageSendQueue.Enqueue(message); senderTask ??= Task.Run(ProcessSendQueue); } +#endif } - private async Task ProcessSendQueue() { try @@ -303,6 +432,45 @@ public WebSocketState GetState() { return Ws!.State; } +#if UNITY_WEBGL && !UNITY_EDITOR + public void HandleWebGLOpen(int socketId) + { + if (socketId == _webglSocketId) + { + _isConnected = true; + if (OnConnect != null) + dispatchQueue.Enqueue(() => OnConnect()); + } + } + + public void HandleWebGLMessage(int socketId, byte[] message) + { + if (socketId == _webglSocketId && OnMessage != null) + { + dispatchQueue.Enqueue(() => OnMessage(message, DateTime.UtcNow)); + } + } + + public void HandleWebGLClose(int socketId, int code, string reason) + { + UnityEngine.Debug.Log($"HandleWebGLClose: {code} {reason}"); + if (socketId == _webglSocketId && OnClose != null) + { + _isConnected = false; + var ex = code != (int)WebSocketCloseStatus.NormalClosure ? new Exception($"WebSocket closed with code {code}: {reason}") : null; + dispatchQueue.Enqueue(() => OnClose?.Invoke(ex)); + } + } + + public void HandleWebGLError(int socketId) + { + UnityEngine.Debug.Log($"HandleWebGLError: {socketId}"); + if (socketId == _webglSocketId && OnConnectError != null) + { + dispatchQueue.Enqueue(() => OnConnectError(new Exception($"Socket {socketId} error."))); + } + } +#endif public void Update() { From c99c4cb3769a48160fba907bc219b53e67377ddd Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:43:28 -0700 Subject: [PATCH 202/223] Update DLLs to 1.1.1 (#300) ## Description of Changes Just bumping the DLLs for a version number update. No actual changes. ## API No breaking changes ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing Just existing CI. This only bumps versions. --------- Co-authored-by: Zeke Foppa --- .../{1.1.0.meta => 1.1.1.meta} | 0 .../{1.1.0 => 1.1.1}/analyzers.meta | 0 .../{1.1.0 => 1.1.1}/analyzers/dotnet.meta | 0 .../{1.1.0 => 1.1.1}/analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 64512 -> 64512 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.1.0 => 1.1.1}/lib.meta | 0 .../{1.1.0 => 1.1.1}/lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 67584 -> 67584 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0.meta => 1.1.1.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (98%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/lib/netstandard2.1.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll (98%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.1.0 => 1.1.1}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll similarity index 98% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 0ba94560c77bae7c061e200358faaf1c257f696d..8ae0c82ba73591ea328c138fbf08acdf6ea84a45 100755 GIT binary patch delta 301 zcmZqp!QAkJc|r$EQVi$OjXhm8jEtMbYdb>)?ykyU^k!P%M|0}q|`Jc)8yn7OH+%~R5R1GL<@^#Q^Oqu;wcLOWga(b4S|YZBf_ETQ_gG#4crS zpl86qV9dy%X9$D_+NS1diRQ+Z$z~~OX$D3qh6afy=H`}$#+JsZmT3mbDMo2YX2xd5 z2Aki#`NqtWqH*Z_48kp%o)-c5`m;KgC#>U zgBe2#ke|k2z+ePq83O4<1{0vHIZ)ORtj3rj703puNCv7f0lTy=+Op}vSEKMy^Q_W1%5-lu}O%0O_jLeMFQcO}T zHwXQ?#muttnnC+ygMR@6%l2$2s&P5#(B%KZT75_JkI57MEmeRD8XSTOf>eLl+V|oS z$GbHGH}Y*ahyJ%@%XKlT{Z0 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.0/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.1.1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta From 3ed21c4910975b7ed4383544deef59d07cc566e2 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Wed, 23 Apr 2025 10:36:30 -0700 Subject: [PATCH 203/223] Bump version to 1.1.2 (#301) ## Description of Changes Bumping the version since 1.1.1 has been released. ## API No breaking changes ## Requires SpacetimeDB PRs None ## Testsuite SpacetimeDB branch name: master ## Testing None, just a version bump. Co-authored-by: Zeke Foppa --- sdks/csharp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/package.json b/sdks/csharp/package.json index a627246adc9..5d31908a8d9 100644 --- a/sdks/csharp/package.json +++ b/sdks/csharp/package.json @@ -1,7 +1,7 @@ { "name": "com.clockworklabs.spacetimedbsdk", "displayName": "SpacetimeDB SDK", - "version": "1.1.1", + "version": "1.1.2", "description": "The SpacetimeDB Client SDK is a software development kit (SDK) designed to interact with and manipulate SpacetimeDB modules..", "keywords": [], "author": { From b6f8362b75900df840945b840192a81d817abcda Mon Sep 17 00:00:00 2001 From: james gilles Date: Wed, 23 Apr 2025 13:50:53 -0700 Subject: [PATCH 204/223] Implement OnUnhandledReducerError (#295) ## Description of Changes SDK side of https://github.com/clockworklabs/SpacetimeDB/pull/2636 Addresses https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/281 ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2636 ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: jgilles/on-unhandled-reducer-error ## Testing - [ ] Add a test that this works to the regression-tests example module --- .../Reducers/IdentityConnected.g.cs | 13 +- .../Reducers/IdentityDisconnected.g.cs | 13 +- .../module_bindings/Reducers/SendMessage.g.cs | 13 +- .../module_bindings/Reducers/SetName.g.cs | 13 +- .../module_bindings/SpacetimeDBClient.g.cs | 748 ++++++++++-------- .../regression-tests/client/Program.cs | 15 +- .../client/module_bindings/Reducers/Add.g.cs | 13 +- .../module_bindings/Reducers/Delete.g.cs | 13 +- .../module_bindings/Reducers/ThrowError.g.cs | 73 ++ .../module_bindings/SpacetimeDBClient.g.cs | 45 +- .../examples~/regression-tests/server/Lib.cs | 6 + sdks/csharp/tools~/update-against-stdb.sh | 2 +- 12 files changed, 608 insertions(+), 359 deletions(-) create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ThrowError.g.cs diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs index 688edfb2eb3..9cefef47ae5 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityConnected.g.cs @@ -17,7 +17,18 @@ public sealed partial class RemoteReducers : RemoteBase public bool InvokeIdentityConnected(ReducerEventContext ctx, Reducer.IdentityConnected args) { - if (OnIdentityConnected == null) return false; + if (OnIdentityConnected == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } OnIdentityConnected( ctx ); diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs index b44f2ed76a6..7748f576d3f 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/IdentityDisconnected.g.cs @@ -17,7 +17,18 @@ public sealed partial class RemoteReducers : RemoteBase public bool InvokeIdentityDisconnected(ReducerEventContext ctx, Reducer.IdentityDisconnected args) { - if (OnIdentityDisconnected == null) return false; + if (OnIdentityDisconnected == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } OnIdentityDisconnected( ctx ); diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs index 3a198619ec2..f138cacf43b 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SendMessage.g.cs @@ -22,7 +22,18 @@ public void SendMessage(string text) public bool InvokeSendMessage(ReducerEventContext ctx, Reducer.SendMessage args) { - if (OnSendMessage == null) return false; + if (OnSendMessage == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } OnSendMessage( ctx, args.Text diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs index cd0429e3ecb..bae09619d11 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/Reducers/SetName.g.cs @@ -22,7 +22,18 @@ public void SetName(string name) public bool InvokeSetName(ReducerEventContext ctx, Reducer.SetName args) { - if (OnSetName == null) return false; + if (OnSetName == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } OnSetName( ctx, args.Name diff --git a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs index 7738e22e2c0..40daa6e38fd 100644 --- a/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs @@ -14,6 +14,7 @@ public sealed partial class RemoteReducers : RemoteBase { internal RemoteReducers(DbConnection conn, SetReducerFlags flags) : base(conn) => SetCallReducerFlags = flags; internal readonly SetReducerFlags SetCallReducerFlags; + internal event Action? InternalOnUnhandledReducerError; } public sealed partial class RemoteTables : RemoteTablesBase @@ -27,379 +28,421 @@ public RemoteTables(DbConnection conn) public sealed partial class SetReducerFlags { } - public interface IRemoteDbContext : IDbContext { } + public interface IRemoteDbContext : IDbContext + { + public event Action? OnUnhandledReducerError; + } + + public sealed class EventContext : IEventContext, IRemoteDbContext + { + private readonly DbConnection conn; - public sealed class EventContext : IEventContext, IRemoteDbContext + /// + /// The event that caused this callback to run. + /// + public readonly Event Event; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() { - private readonly DbConnection conn; - - /// - /// The event that caused this callback to run. - /// - public readonly Event Event; - - /// - /// Access to tables in the client cache, which stores a read-only replica of the remote database state. - /// - /// The returned DbView will have a method to access each table defined by the module. - /// - public RemoteTables Db => conn.Db; - /// - /// Access to reducers defined by the module. - /// - /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, - /// plus methods for adding and removing callbacks on each of those reducers. - /// - public RemoteReducers Reducers => conn.Reducers; - /// - /// Access to setters for per-reducer flags. - /// - /// The returned SetReducerFlags will have a method to invoke, - /// for each reducer defined by the module, - /// which call-flags for the reducer can be set. - /// - public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - /// - /// Returns true if the connection is active, i.e. has not yet disconnected. - /// - public bool IsActive => conn.IsActive; - /// - /// Close the connection. - /// - /// Throws an error if the connection is already closed. - /// - public void Disconnect() { - conn.Disconnect(); - } - /// - /// Start building a subscription. - /// - /// A builder-pattern constructor for subscribing to queries, - /// causing matching rows to be replicated into the client cache. - public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); - /// - /// Get the Identity of this connection. - /// - /// This method returns null if the connection was constructed anonymously - /// and we have not yet received our newly-generated Identity from the host. - /// - public Identity? Identity => conn.Identity; - /// - /// Get this connection's ConnectionId. - /// - public ConnectionId ConnectionId => conn.ConnectionId; - - internal EventContext(DbConnection conn, Event Event) - { - this.conn = conn; - this.Event = Event; - } + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; } - public sealed class ReducerEventContext : IReducerEventContext, IRemoteDbContext + internal EventContext(DbConnection conn, Event Event) { - private readonly DbConnection conn; - /// - /// The reducer event that caused this callback to run. - /// - public readonly ReducerEvent Event; - - /// - /// Access to tables in the client cache, which stores a read-only replica of the remote database state. - /// - /// The returned DbView will have a method to access each table defined by the module. - /// - public RemoteTables Db => conn.Db; - /// - /// Access to reducers defined by the module. - /// - /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, - /// plus methods for adding and removing callbacks on each of those reducers. - /// - public RemoteReducers Reducers => conn.Reducers; - /// - /// Access to setters for per-reducer flags. - /// - /// The returned SetReducerFlags will have a method to invoke, - /// for each reducer defined by the module, - /// which call-flags for the reducer can be set. - /// - public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - /// - /// Returns true if the connection is active, i.e. has not yet disconnected. - /// - public bool IsActive => conn.IsActive; - /// - /// Close the connection. - /// - /// Throws an error if the connection is already closed. - /// - public void Disconnect() { - conn.Disconnect(); - } - /// - /// Start building a subscription. - /// - /// A builder-pattern constructor for subscribing to queries, - /// causing matching rows to be replicated into the client cache. - public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); - /// - /// Get the Identity of this connection. - /// - /// This method returns null if the connection was constructed anonymously - /// and we have not yet received our newly-generated Identity from the host. - /// - public Identity? Identity => conn.Identity; - /// - /// Get this connection's ConnectionId. - /// - public ConnectionId ConnectionId => conn.ConnectionId; - - internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) - { - this.conn = conn; - Event = reducerEvent; - } + this.conn = conn; + this.Event = Event; } + } + + public sealed class ReducerEventContext : IReducerEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The reducer event that caused this callback to run. + /// + public readonly ReducerEvent Event; - public sealed class ErrorContext : IErrorContext, IRemoteDbContext + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() { - private readonly DbConnection conn; - /// - /// The Exception that caused this error callback to be run. - /// - public readonly Exception Event; - Exception IErrorContext.Event { - get { - return Event; - } - } - - /// - /// Access to tables in the client cache, which stores a read-only replica of the remote database state. - /// - /// The returned DbView will have a method to access each table defined by the module. - /// - public RemoteTables Db => conn.Db; - /// - /// Access to reducers defined by the module. - /// - /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, - /// plus methods for adding and removing callbacks on each of those reducers. - /// - public RemoteReducers Reducers => conn.Reducers; - /// - /// Access to setters for per-reducer flags. - /// - /// The returned SetReducerFlags will have a method to invoke, - /// for each reducer defined by the module, - /// which call-flags for the reducer can be set. - /// - public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - /// - /// Returns true if the connection is active, i.e. has not yet disconnected. - /// - public bool IsActive => conn.IsActive; - /// - /// Close the connection. - /// - /// Throws an error if the connection is already closed. - /// - public void Disconnect() { - conn.Disconnect(); - } - /// - /// Start building a subscription. - /// - /// A builder-pattern constructor for subscribing to queries, - /// causing matching rows to be replicated into the client cache. - public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); - /// - /// Get the Identity of this connection. - /// - /// This method returns null if the connection was constructed anonymously - /// and we have not yet received our newly-generated Identity from the host. - /// - public Identity? Identity => conn.Identity; - /// - /// Get this connection's ConnectionId. - /// - public ConnectionId ConnectionId => conn.ConnectionId; - - internal ErrorContext(DbConnection conn, Exception error) - { - this.conn = conn; - Event = error; - } + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; } - public sealed class SubscriptionEventContext : ISubscriptionEventContext, IRemoteDbContext + internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) { - private readonly DbConnection conn; - - /// - /// Access to tables in the client cache, which stores a read-only replica of the remote database state. - /// - /// The returned DbView will have a method to access each table defined by the module. - /// - public RemoteTables Db => conn.Db; - /// - /// Access to reducers defined by the module. - /// - /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, - /// plus methods for adding and removing callbacks on each of those reducers. - /// - public RemoteReducers Reducers => conn.Reducers; - /// - /// Access to setters for per-reducer flags. - /// - /// The returned SetReducerFlags will have a method to invoke, - /// for each reducer defined by the module, - /// which call-flags for the reducer can be set. - /// - public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; - /// - /// Returns true if the connection is active, i.e. has not yet disconnected. - /// - public bool IsActive => conn.IsActive; - /// - /// Close the connection. - /// - /// Throws an error if the connection is already closed. - /// - public void Disconnect() { - conn.Disconnect(); - } - /// - /// Start building a subscription. - /// - /// A builder-pattern constructor for subscribing to queries, - /// causing matching rows to be replicated into the client cache. - public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); - /// - /// Get the Identity of this connection. - /// - /// This method returns null if the connection was constructed anonymously - /// and we have not yet received our newly-generated Identity from the host. - /// - public Identity? Identity => conn.Identity; - /// - /// Get this connection's ConnectionId. - /// - public ConnectionId ConnectionId => conn.ConnectionId; - - internal SubscriptionEventContext(DbConnection conn) + this.conn = conn; + Event = reducerEvent; + } + } + + public sealed class ErrorContext : IErrorContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The Exception that caused this error callback to be run. + /// + public readonly Exception Event; + Exception IErrorContext.Event + { + get { - this.conn = conn; + return Event; } } /// - /// Builder-pattern constructor for subscription queries. + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. /// - public sealed class SubscriptionBuilder + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() { - private readonly IDbConnection conn; + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } - private event Action? Applied; - private event Action? Error; + internal ErrorContext(DbConnection conn, Exception error) + { + this.conn = conn; + Event = error; + } + } - /// - /// Private API, use conn.SubscriptionBuilder() instead. - /// - public SubscriptionBuilder(IDbConnection conn) - { - this.conn = conn; - } + public sealed class SubscriptionEventContext : ISubscriptionEventContext, IRemoteDbContext + { + private readonly DbConnection conn; - /// - /// Register a callback to run when the subscription is applied. - /// - public SubscriptionBuilder OnApplied( - Action callback - ) - { - Applied += callback; - return this; - } + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to setters for per-reducer flags. + /// + /// The returned SetReducerFlags will have a method to invoke, + /// for each reducer defined by the module, + /// which call-flags for the reducer can be set. + /// + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } - /// - /// Register a callback to run when the subscription fails. - /// - /// Note that this callback may run either when attempting to apply the subscription, - /// in which case Self::on_applied will never run, - /// or later during the subscription's lifetime if the module's interface changes, - /// in which case Self::on_applied may have already run. - /// - public SubscriptionBuilder OnError( - Action callback - ) - { - Error += callback; - return this; - } + internal SubscriptionEventContext(DbConnection conn) + { + this.conn = conn; + } + } - /// - /// Subscribe to the following SQL queries. - /// - /// This method returns immediately, with the data not yet added to the DbConnection. - /// The provided callbacks will be invoked once the data is returned from the remote server. - /// Data from all the provided queries will be returned at the same time. - /// - /// See the SpacetimeDB SQL docs for more information on SQL syntax: - /// https://spacetimedb.com/docs/sql - /// - public SubscriptionHandle Subscribe( - string[] querySqls - ) => new(conn, Applied, Error, querySqls); - - /// - /// Subscribe to all rows from all tables. - /// - /// This method is intended as a convenience - /// for applications where client-side memory use and network bandwidth are not concerns. - /// Applications where these resources are a constraint - /// should register more precise queries via Self.Subscribe - /// in order to replicate only the subset of data which the client needs to function. - /// - /// This method should not be combined with Self.Subscribe on the same DbConnection. - /// A connection may either Self.Subscribe to particular queries, - /// or Self.SubscribeToAllTables, but not both. - /// Attempting to call Self.Subscribe - /// on a DbConnection that has previously used Self.SubscribeToAllTables, - /// or vice versa, may misbehave in any number of ways, - /// including dropping subscriptions, corrupting the client cache, or panicking. - /// - public void SubscribeToAllTables() - { - // Make sure we use the legacy handle constructor here, even though there's only 1 query. - // We drop the error handler, since it can't be called for legacy subscriptions. - new SubscriptionHandle( - conn, - Applied, - new string[] { "SELECT * FROM *" } - ); - } + /// + /// Builder-pattern constructor for subscription queries. + /// + public sealed class SubscriptionBuilder + { + private readonly IDbConnection conn; + + private event Action? Applied; + private event Action? Error; + + /// + /// Private API, use conn.SubscriptionBuilder() instead. + /// + public SubscriptionBuilder(IDbConnection conn) + { + this.conn = conn; + } + + /// + /// Register a callback to run when the subscription is applied. + /// + public SubscriptionBuilder OnApplied( + Action callback + ) + { + Applied += callback; + return this; + } + + /// + /// Register a callback to run when the subscription fails. + /// + /// Note that this callback may run either when attempting to apply the subscription, + /// in which case Self::on_applied will never run, + /// or later during the subscription's lifetime if the module's interface changes, + /// in which case Self::on_applied may have already run. + /// + public SubscriptionBuilder OnError( + Action callback + ) + { + Error += callback; + return this; } - public sealed class SubscriptionHandle : SubscriptionHandleBase { - /// - /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. - /// - public SubscriptionHandle(IDbConnection conn, Action? onApplied, string[] querySqls) : base(conn, onApplied, querySqls) - { } - - /// - /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. - /// - public SubscriptionHandle( - IDbConnection conn, - Action? onApplied, - Action? onError, - string[] querySqls - ) : base(conn, onApplied, onError, querySqls) - { } + /// + /// Subscribe to the following SQL queries. + /// + /// This method returns immediately, with the data not yet added to the DbConnection. + /// The provided callbacks will be invoked once the data is returned from the remote server. + /// Data from all the provided queries will be returned at the same time. + /// + /// See the SpacetimeDB SQL docs for more information on SQL syntax: + /// https://spacetimedb.com/docs/sql + /// + public SubscriptionHandle Subscribe( + string[] querySqls + ) => new(conn, Applied, Error, querySqls); + + /// + /// Subscribe to all rows from all tables. + /// + /// This method is intended as a convenience + /// for applications where client-side memory use and network bandwidth are not concerns. + /// Applications where these resources are a constraint + /// should register more precise queries via Self.Subscribe + /// in order to replicate only the subset of data which the client needs to function. + /// + /// This method should not be combined with Self.Subscribe on the same DbConnection. + /// A connection may either Self.Subscribe to particular queries, + /// or Self.SubscribeToAllTables, but not both. + /// Attempting to call Self.Subscribe + /// on a DbConnection that has previously used Self.SubscribeToAllTables, + /// or vice versa, may misbehave in any number of ways, + /// including dropping subscriptions, corrupting the client cache, or panicking. + /// + public void SubscribeToAllTables() + { + // Make sure we use the legacy handle constructor here, even though there's only 1 query. + // We drop the error handler, since it can't be called for legacy subscriptions. + new SubscriptionHandle( + conn, + Applied, + new string[] { "SELECT * FROM *" } + ); } + } + + public sealed class SubscriptionHandle : SubscriptionHandleBase + { + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle(IDbConnection conn, Action? onApplied, string[] querySqls) : base(conn, onApplied, querySqls) + { } + + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle( + IDbConnection conn, + Action? onApplied, + Action? onError, + string[] querySqls + ) : base(conn, onApplied, onError, querySqls) + { } + } public abstract partial class Reducer { @@ -421,7 +464,8 @@ public DbConnection() protected override Reducer ToReducer(TransactionUpdate update) { var encodedArgs = update.ReducerCall.Args; - return update.ReducerCall.ReducerName switch { + return update.ReducerCall.ReducerName switch + { "identity_connected" => BSATNHelpers.Decode(encodedArgs), "identity_disconnected" => BSATNHelpers.Decode(encodedArgs), "send_message" => BSATNHelpers.Decode(encodedArgs), @@ -445,7 +489,8 @@ protected override IErrorContext ToErrorContext(Exception exception) => protected override bool Dispatch(IReducerEventContext context, Reducer reducer) { var eventContext = (ReducerEventContext)context; - return reducer switch { + return reducer switch + { Reducer.IdentityConnected args => Reducers.InvokeIdentityConnected(eventContext, args), Reducer.IdentityDisconnected args => Reducers.InvokeIdentityDisconnected(eventContext, args), Reducer.SendMessage args => Reducers.InvokeSendMessage(eventContext, args), @@ -455,5 +500,10 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) } public SubscriptionBuilder SubscriptionBuilder() => new(this); + public event Action OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } } } diff --git a/sdks/csharp/examples~/regression-tests/client/Program.cs b/sdks/csharp/examples~/regression-tests/client/Program.cs index 78864ef75db..5e79220ccf8 100644 --- a/sdks/csharp/examples~/regression-tests/client/Program.cs +++ b/sdks/csharp/examples~/regression-tests/client/Program.cs @@ -65,6 +65,13 @@ void OnConnected(DbConnection conn, Identity identity, string authToken) waiting--; ValidateBTreeIndexes(ctx); }; + + conn.OnUnhandledReducerError += (ReducerEventContext ctx, Exception exception) => + { + Log.Info($"Got OnUnhandledReducerError: {exception}"); + waiting--; + ValidateBTreeIndexes(ctx); + }; } const uint MAX_ID = 10; @@ -92,12 +99,13 @@ void ValidateBTreeIndexes(IRemoteDbContext conn) void OnSubscriptionApplied(SubscriptionEventContext context) { + applied = true; + // Do some operations that alter row state; // we will check that everything is in sync in the callbacks for these reducer calls. Log.Debug("Calling Add"); waiting++; context.Reducers.Add(1, 1); - applied = true; Log.Debug("Calling Delete"); waiting++; @@ -106,7 +114,10 @@ void OnSubscriptionApplied(SubscriptionEventContext context) Log.Debug("Calling Add"); waiting++; context.Reducers.Add(1, 1); - applied = true; + + Log.Debug("Calling ThrowError"); + waiting++; + context.Reducers.ThrowError("this is an error"); // Now unsubscribe and check that the unsubscribe is actually applied. Log.Debug("Calling Unsubscribe"); diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs index 0820f6a20d3..200ebc1c43c 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Add.g.cs @@ -22,7 +22,18 @@ public void Add(uint id, uint indexed) public bool InvokeAdd(ReducerEventContext ctx, Reducer.Add args) { - if (OnAdd == null) return false; + if (OnAdd == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } OnAdd( ctx, args.Id, diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs index f2fb372abfd..fdc083d7ae4 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/Delete.g.cs @@ -22,7 +22,18 @@ public void Delete(uint id) public bool InvokeDelete(ReducerEventContext ctx, Reducer.Delete args) { - if (OnDelete == null) return false; + if (OnDelete == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } OnDelete( ctx, args.Id diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ThrowError.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ThrowError.g.cs new file mode 100644 index 00000000000..64685d4f872 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/ThrowError.g.cs @@ -0,0 +1,73 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void ThrowErrorHandler(ReducerEventContext ctx, string error); + public event ThrowErrorHandler? OnThrowError; + + public void ThrowError(string error) + { + conn.InternalCallReducer(new Reducer.ThrowError(error), this.SetCallReducerFlags.ThrowErrorFlags); + } + + public bool InvokeThrowError(ReducerEventContext ctx, Reducer.ThrowError args) + { + if (OnThrowError == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnThrowError( + ctx, + args.Error + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ThrowError : Reducer, IReducerArgs + { + [DataMember(Name = "error")] + public string Error; + + public ThrowError(string Error) + { + this.Error = Error; + } + + public ThrowError() + { + this.Error = ""; + } + + string IReducerArgs.ReducerName => "ThrowError"; + } + } + + public sealed partial class SetReducerFlags + { + internal CallReducerFlags ThrowErrorFlags; + public void ThrowError(CallReducerFlags flags) => ThrowErrorFlags = flags; + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs index 01c6abeda59..0aa690dda66 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs @@ -14,6 +14,7 @@ public sealed partial class RemoteReducers : RemoteBase { internal RemoteReducers(DbConnection conn, SetReducerFlags flags) : base(conn) => SetCallReducerFlags = flags; internal readonly SetReducerFlags SetCallReducerFlags; + internal event Action? InternalOnUnhandledReducerError; } public sealed partial class RemoteTables : RemoteTablesBase @@ -26,7 +27,10 @@ public RemoteTables(DbConnection conn) public sealed partial class SetReducerFlags { } - public interface IRemoteDbContext : IDbContext { } + public interface IRemoteDbContext : IDbContext + { + public event Action? OnUnhandledReducerError; + } public sealed class EventContext : IEventContext, IRemoteDbContext { @@ -88,6 +92,14 @@ public void Disconnect() /// Get this connection's ConnectionId. /// public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } internal EventContext(DbConnection conn, Event Event) { @@ -155,6 +167,14 @@ public void Disconnect() /// Get this connection's ConnectionId. /// public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) { @@ -229,6 +249,14 @@ public void Disconnect() /// Get this connection's ConnectionId. ///
    + /// Subscribe to the following SQL queries. + /// + /// This method returns immediately, with the data not yet added to the DbConnection. + /// The provided callbacks will be invoked once the data is returned from the remote server. + /// Data from all the provided queries will be returned at the same time. + /// + /// See the SpacetimeDB SQL docs for more information on SQL syntax: + /// https://spacetimedb.com/docs/sql + ///
    + /// Subscribe to the following SQL queries. + /// + /// This method returns immediately, with the data not yet added to the DbConnection. + /// The provided callbacks will be invoked once the data is returned from the remote server. + /// Data from all the provided queries will be returned at the same time. + /// + /// See the SpacetimeDB SQL docs for more information on SQL syntax: + /// https://spacetimedb.com/docs/sql + ///
    Create an Address from a BIG-ENDIAN byte array. @@ -233,7 +173,7 @@ - + Create an Identity from a LITTLE-ENDIAN byte array. @@ -242,7 +182,7 @@ - + Create an Identity from a LITTLE-ENDIAN byte array. @@ -251,7 +191,7 @@ - + Create an Identity from a BIG-ENDIAN byte array. From 39e7ebbb9a8978eb2bad413a1cd0e2708edef75d Mon Sep 17 00:00:00 2001 From: Phoebe Goldman Date: Tue, 14 Jan 2025 13:43:34 -0500 Subject: [PATCH 157/223] Revise `WithCredentials` to `WithToken` (#212) ## Description of Changes `WithCredentials` was designed for our old auth model, where tokens were always issued by the SpacetimeDB host alongside an `Identity`, and therefore the bearer always knew their `Identity`. In our new auth model, a client may have a valid auth-able JWT but not know what `Identity` it will result in, as the `Identity` is computed based on the hash of some of the token's contents, and this hashing algorithm is not included in our client SDKs. As such, this PR revises `WithCredentials` to `WithToken`, which just accepts the token. ## API - [x] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* `WithCredentials` is renamed and its signature changes. ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] @cloutiertyler should test this with the Unity tutorial, if possible. --------- Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com> --- sdks/csharp/examples~/quickstart/client/Program.cs | 2 +- sdks/csharp/src/SpacetimeDBClient.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index e8e3bcd96a1..9eb43b13be8 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -25,7 +25,7 @@ void Main() conn = DbConnection.Builder() .WithUri(HOST) .WithModuleName(DBNAME) - //.WithCredentials((null, AuthToken.Token)) + //.WithToken(AuthToken.Token) .OnConnect(OnConnect) .OnConnectError(OnConnectError) .OnDisconnect(OnDisconnect) diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 6720767fd5d..6e22eb7700e 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -57,9 +57,9 @@ public DbConnectionBuilder WithModuleName(string nameOrAd return this; } - public DbConnectionBuilder WithCredentials(in (Identity identity, string token)? creds) + public DbConnectionBuilder WithToken(string? token) { - token = creds?.token; + this.token = token; return this; } From 2487c94967497080ee369159df583600f363eed2 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 14 Jan 2025 20:25:45 +0100 Subject: [PATCH 158/223] Add CI check for Unity meta files (#209) ## Description of Changes Adds CI check to prevent issues like #208. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] Describe a test for this PR that you have completed --- sdks/csharp/.github/workflows/unity-test.yml | 7 + sdks/csharp/packages/.gitignore | 3 + .../SpacetimeDB.BSATN.Runtime.xml | 559 ------------------ 3 files changed, 10 insertions(+), 559 deletions(-) delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml diff --git a/sdks/csharp/.github/workflows/unity-test.yml b/sdks/csharp/.github/workflows/unity-test.yml index 6312cb929fa..97f5e31e1c4 100644 --- a/sdks/csharp/.github/workflows/unity-test.yml +++ b/sdks/csharp/.github/workflows/unity-test.yml @@ -15,6 +15,13 @@ jobs: with: submodules: true + - name: Check Unity meta files + uses: DeNA/unity-meta-check@v3 + with: + enable_pr_comment: true + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + # Grab the branch name from the PR description. If it's not found, master will be used instead. - name: Extract SpacetimeDB branch name or PR link from PR description id: extract-branch diff --git a/sdks/csharp/packages/.gitignore b/sdks/csharp/packages/.gitignore index 5602e9e9759..7d9dea737b9 100644 --- a/sdks/csharp/packages/.gitignore +++ b/sdks/csharp/packages/.gitignore @@ -6,3 +6,6 @@ !/*/*/lib !/*/*/lib.meta + +# Ignore XML documentation metadata from packages too. +*.xml diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml deleted file mode 100755 index b95737b6a3b..00000000000 --- a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml +++ /dev/null @@ -1,559 +0,0 @@ - - - - SpacetimeDB.BSATN.Runtime - - - - Represents a 128-bit signed integer. - - - Initializes a new instance of the struct. - The upper 64-bits of the 128-bit value. - The lower 64-bits of the 128-bit value. - - - - - - - - - - - - - - - - - - - - - Implicitly converts a value to a 128-bit signed integer. - The value to convert. - converted to a 128-bit signed integer. - - - Represents a 256-bit signed integer. - - - Initializes a new instance of the struct. - The upper 128-bits of the 256-bit value. - The lower 128-bits of the 256-bit value. - - - - - - - - - - - - - - - - - - - - - Represents a 128-bit unsigned integer. - - - Initializes a new instance of the struct. - The upper 64-bits of the 128-bit value. - The lower 64-bits of the 128-bit value. - - - - - - - - - - - - - - - - - - Represents a 128-bit unsigned integer. - - - Initializes a new instance of the struct. - The upper 128-bits of the 256-bit value. - The lower 128-bits of the 256-bit value. - - - - - - - - - - - - - - - - - - - Convert this object to a BIG-ENDIAN hex string. - - Big endian is almost always the correct convention here. It puts the most significant bytes - of the number at the lowest indexes of the resulting string; assuming the string is printed - with low indexes to the left, this will result in the correct hex number being displayed. - - (This might be wrong if the string is printed after, say, a unicode right-to-left marker. - But, well, what can you do.) - - - - - - - - Convert the passed byte array to a value of type T, optionally reversing it before performing the conversion. - If the input is not reversed, it is treated as having the native endianness of the host system. - (The endianness of the host system can be checked via System.BitConverter.IsLittleEndian.) - - - - - - - - - Convert a hex string to a byte array. - - - - - - - Create an Address from a LITTLE-ENDIAN byte array. - - If you are parsing an Address from a string, you probably want FromHexString instead, - or, failing that, FromBigEndian. - - Returns null if the resulting address is the default. - - - - - - Create an Address from a BIG-ENDIAN byte array. - - This method is the correct choice if you have converted the bytes of a hexadecimal-formatted Address - to a byte array in the following way: - - "0xb0b1b2..." - -> - [0xb0, 0xb1, 0xb2, ...] - - Returns null if the resulting address is the default. - - - - - - Create an Address from a hex string. - - - - - - - Create an Identity from a LITTLE-ENDIAN byte array. - - If you are parsing an Identity from a string, you probably want FromHexString instead, - or, failing that, FromBigEndian. - - - - - - Create an Identity from a LITTLE-ENDIAN byte array. - - If you are parsing an Identity from a string, you probably want FromHexString instead, - or, failing that, FromBigEndian. - - - - - - Create an Identity from a BIG-ENDIAN byte array. - - This method is the correct choice if you have converted the bytes of a hexadecimal-formatted `Identity` - to a byte array in the following way: - - "0xb0b1b2..." - -> - [0xb0, 0xb1, 0xb2, ...] - - - - - - Create an Identity from a hex string. - - - - - - - Indicates that an API is experimental and it may change in the future. - - - This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental - feature is used. Authors can use this attribute to ship preview features in their assemblies. - - - - - Initializes a new instance of the class, - specifying the ID that the compiler will use when reporting a use of the API the attribute applies to. - - The ID that the compiler will use when reporting a use of the API the attribute applies to. - - - - Gets the ID that the compiler will use when reporting a use of the API the attribute applies to. - - The unique diagnostic ID. - - The diagnostic ID is shown in build output for warnings and errors. - This property represents the unique ID that can be used to suppress the warnings or errors, if needed. - - - - - Gets or sets the URL for corresponding documentation. - The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID. - - The format string that represents a URL to corresponding documentation. - An example format string is https://contoso.com/obsoletion-warnings/{0}. - - - - Specifies that the method or property will ensure that the listed field and property members have not-null values. - - - - - Initializes the attribute with a field or property member. - - The field or property member that is promised to be not-null. - - - - Initializes the attribute with the list of field and property members. - - The list of field and property members that are promised to be not-null. - - - - Gets field or property member names. - - - - - Specifies that the method or property will ensure that the listed field and property - members have not-null values when returning with the specified return value condition. - - - - - Initializes the attribute with the specified return value condition and a field or property member. - - The return value condition. If the method returns this value, the associated parameter will not be null. - The field or property member that is promised to be not-null. - - - - Initializes the attribute with the specified return value condition and list of field and property members. - - The return value condition. If the method returns this value, the associated parameter will not be null. - The list of field and property members that are promised to be not-null. - - - - Gets the return value condition. - - - - - Gets field or property member names. - - - - - Specifies that this constructor sets all required members for the current type, - and callers do not need to set any required members themselves. - - - - - Specifies the syntax used in a string. - - - - - Initializes the with the identifier of the syntax used. - - The syntax identifier. - - - Initializes the with the identifier of the syntax used. - The syntax identifier. - Optional arguments associated with the specific syntax employed. - - - Gets the identifier of the syntax used. - - - Optional arguments associated with the specific syntax employed. - - - The syntax identifier for strings containing composite formats for string formatting. - - - The syntax identifier for strings containing date format specifiers. - - - The syntax identifier for strings containing date and time format specifiers. - - - The syntax identifier for strings containing format specifiers. - - - The syntax identifier for strings containing format specifiers. - - - The syntax identifier for strings containing JavaScript Object Notation (JSON). - - - The syntax identifier for strings containing numeric format specifiers. - - - The syntax identifier for strings containing regular expressions. - - - The syntax identifier for strings containing time format specifiers. - - - The syntax identifier for strings containing format specifiers. - - - The syntax identifier for strings containing URIs. - - - The syntax identifier for strings containing XML. - - - - Used to indicate a byref escapes and is not scoped. - - - - There are several cases where the C# compiler treats a as implicitly - - where the compiler does not allow the to escape the method. - - - For example: - - for instance methods. - parameters that refer to types. - parameters. - - - - This attribute is used in those instances where the should be allowed to escape. - - - Applying this attribute, in any form, has impact on consumers of the applicable API. It is necessary for - API authors to understand the lifetime implications of applying this attribute and how it may impact their users. - - - - - - An attribute that allows parameters to receive the expression of other parameters. - - - - - Initializes a new instance of the class. - - The condition parameter value. - - - - Gets the parameter name the expression is retrieved from. - - - - - Initialize the attribute to refer to the method on the type. - - The type of the builder to use to construct the collection. - The name of the method on the builder to use to construct the collection. - - must refer to a static method that accepts a single parameter of - type and returns an instance of the collection being built containing - a copy of the data from that span. In future releases of .NET, additional patterns may be supported. - - - - - Gets the type of the builder to use to construct the collection. - - - - - Gets the name of the method on the builder to use to construct the collection. - - - This should match the metadata name of the target method. - For example, this might be ".ctor" if targeting the type's constructor. - - - - - Indicates that compiler support for a particular feature is required for the location where this attribute is applied. - - - - - Creates a new instance of the type. - - The name of the feature to indicate. - - - - The name of the compiler feature. - - - - - If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand . - - - - - The used for the ref structs C# feature. - - - - - The used for the required members C# feature. - - - - - Indicates which arguments to a method involving an interpolated string handler should be passed to that handler. - - - - - Initializes a new instance of the class. - - The name of the argument that should be passed to the handler. - may be used as the name of the receiver in an instance method. - - - - Initializes a new instance of the class. - - The names of the arguments that should be passed to the handler. - may be used as the name of the receiver in an instance method. - - - - Gets the names of the arguments that should be passed to the handler. - - may be used as the name of the receiver in an instance method. - - - - Indicates the attributed type is to be used as an interpolated string handler. - - - - - Reserved to be used by the compiler for tracking metadata. - This class should not be used by developers in source code. - - - - - Used to indicate to the compiler that a method should be called - in its containing module's initializer. - - - When one or more valid methods - with this attribute are found in a compilation, the compiler will - emit a module initializer which calls each of the attributed methods. - - Certain requirements are imposed on any method targeted with this attribute: - - The method must be `static`. - - The method must be an ordinary member method, as opposed to a property accessor, constructor, local function, etc. - - The method must be parameterless. - - The method must return `void`. - - The method must not be generic or be contained in a generic type. - - The method's effective accessibility must be `internal` or `public`. - - The specification for module initializers in the .NET runtime can be found here: - https://github.com/dotnet/runtime/blob/main/docs/design/specs/Ecma-335-Augments.md#module-initializer - - - - - Specifies that a type has required members or that a member is required. - - - - - Reserved for use by a compiler for tracking metadata. - This attribute should not be used by developers in source code. - - - - - Used to indicate to the compiler that the .locals init flag should not be set in method headers. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class with the specified message. - - An optional message associated with this attribute instance. - - - - Returns the optional message associated with this attribute instance. - - - - - Returns the optional URL associated with this attribute instance. - - - - From 0017af799133aa89ceb8b472ebbd6cc0e72fe0b0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 14 Jan 2025 20:48:20 +0100 Subject: [PATCH 159/223] Disable PR comment for meta file check if not a PR (#216) ## Description of Changes Looks like the .meta check hard-fails on push events if `enable_pr_comment` is `true`, instead of just ignoring it... I hope this fix works, but hard to tell without merging first. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] This is a PR that changes CI configuration, so see CI --- sdks/csharp/.github/workflows/unity-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/csharp/.github/workflows/unity-test.yml b/sdks/csharp/.github/workflows/unity-test.yml index 97f5e31e1c4..44ae050f1be 100644 --- a/sdks/csharp/.github/workflows/unity-test.yml +++ b/sdks/csharp/.github/workflows/unity-test.yml @@ -18,7 +18,7 @@ jobs: - name: Check Unity meta files uses: DeNA/unity-meta-check@v3 with: - enable_pr_comment: true + enable_pr_comment: ${{ github.event_name == 'pull_request' }} env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" From 749825aa2fd0e74d8fa0b351e40bfd0d37bdf150 Mon Sep 17 00:00:00 2001 From: Phoebe Goldman Date: Tue, 14 Jan 2025 18:43:10 -0500 Subject: [PATCH 160/223] `SubscribeToAllTables`, which hides `"SELECT * FROM *"` (#211) ## Description of Changes Per out-of-band discussion, add `SubscriptionBuilder.SubscribeToAllTables`, which abstracts over `SubscriptionBuilder.Subscribe(["SELECT * FROM *"])`. In the future, we will change the implementation of this method, so that it uses "legacy subscriptions" while `SubscriptionBuilder.Subscribe` moves to using "mutable subscriptions." At that time, no other interface will be provided for using "legacy subscriptions." `SubscribeToAllTables` may also at some point be rewritten in terms of "mutable subscriptions" somehow. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs N/a ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] @cloutiertyler will use this in the new tutorial and report back. --------- Co-authored-by: Ingvar Stepanyan Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com> Co-authored-by: Zeke Foppa Co-authored-by: Tyler Cloutier --- sdks/csharp/src/Event.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 8a25349df91..75f30167350 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -63,6 +63,11 @@ public SubscriptionBuilder OnError(Callback callback) } public SubscriptionHandle Subscribe(params string[] querySqls) => new(conn, Applied, Error, querySqls); + + public void SubscribeToAllTables() + { + Subscribe("SELECT * FROM *"); + } } public interface ISubscriptionHandle From 3d530ee24861ba05c5a88b0b12505cc2c78c1556 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 16 Jan 2025 17:29:27 +0000 Subject: [PATCH 161/223] Upgrade to new regenerated client-api bindings (#218) ## Description of Changes Looks like client API bindings haven't been regenerated in a while, and this is a necessary precursor to the new subscription work. This PR fixes the generation script, regenerates the bindings and updates affected code. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: v1.0.0-rc3 ## Testing *Write instructions for a test that you performed for this PR* - [x] Ran regular `dotnet test`. - [x] Checked Unity tests via CI. --- sdks/csharp/src/BSATNHelpers.cs | 3 + .../src/SpacetimeDB/ClientApi/BsatnRowList.cs | 6 +- .../src/SpacetimeDB/ClientApi/CallReducer.cs | 6 +- .../SpacetimeDB/ClientApi/ClientMessage.cs | 4 +- .../ClientApi/CompressableQueryUpdate.cs | 4 +- .../SpacetimeDB/ClientApi/DatabaseUpdate.cs | 4 +- .../src/SpacetimeDB/ClientApi/EnergyQuanta.cs | 4 +- .../src/SpacetimeDB/ClientApi/OneOffQuery.cs | 6 +- .../ClientApi/OneOffQueryResponse.cs | 6 +- .../src/SpacetimeDB/ClientApi/QueryId.cs | 31 ++++++ .../src/SpacetimeDB/ClientApi/QueryId.cs.meta | 11 ++ .../SpacetimeDB/ClientApi/ReducerCallInfo.cs | 6 +- .../SpacetimeDB/ClientApi/ServerMessage.cs | 5 +- .../SpacetimeDB/ClientApi/SubscribeApplied.cs | 47 ++++++++ .../ClientApi/SubscribeApplied.cs.meta | 11 ++ .../SpacetimeDB/ClientApi/SubscribeRows.cs | 43 +++++++ .../ClientApi/SubscribeRows.cs.meta | 11 ++ .../SpacetimeDB/ClientApi/SubscribeSingle.cs | 43 +++++++ .../ClientApi/SubscribeSingle.cs.meta | 11 ++ .../ClientApi/SubscriptionError.cs | 46 ++++++++ .../ClientApi/SubscriptionError.cs.meta | 11 ++ .../src/SpacetimeDB/ClientApi/Timestamp.cs | 4 +- .../src/SpacetimeDB/ClientApi/Unsubscribe.cs | 38 +++++++ .../SpacetimeDB/ClientApi/Unsubscribe.cs.meta | 11 ++ .../ClientApi/UnsubscribeApplied.cs | 47 ++++++++ .../ClientApi/UnsubscribeApplied.cs.meta | 11 ++ sdks/csharp/src/SpacetimeDBClient.cs | 105 +++++++----------- sdks/csharp/tests~/SnapshotTests.cs | 4 +- sdks/csharp/tools~/gen-client-api.sh | 20 ++-- 29 files changed, 452 insertions(+), 107 deletions(-) create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs.meta create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs.meta diff --git a/sdks/csharp/src/BSATNHelpers.cs b/sdks/csharp/src/BSATNHelpers.cs index 9c227e13171..59160657d31 100644 --- a/sdks/csharp/src/BSATNHelpers.cs +++ b/sdks/csharp/src/BSATNHelpers.cs @@ -5,6 +5,9 @@ namespace SpacetimeDB { public static class BSATNHelpers { + public static T Decode(System.Collections.Generic.List bsatn) where T : IStructuralReadWrite, new() => + Decode(bsatn.ToArray()); + public static T Decode(byte[] bsatn) where T : IStructuralReadWrite, new() { using var stream = new MemoryStream(bsatn); diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs index 1f17c790676..f284ff71a63 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs @@ -18,11 +18,11 @@ public partial class BsatnRowList [DataMember(Name = "size_hint")] public SpacetimeDB.ClientApi.RowSizeHint SizeHint; [DataMember(Name = "rows_data")] - public byte[] RowsData; + public System.Collections.Generic.List RowsData; public BsatnRowList( SpacetimeDB.ClientApi.RowSizeHint SizeHint, - byte[] RowsData + System.Collections.Generic.List RowsData ) { this.SizeHint = SizeHint; @@ -32,7 +32,7 @@ byte[] RowsData public BsatnRowList() { this.SizeHint = null!; - this.RowsData = Array.Empty(); + this.RowsData = new(); } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs index 212d9bb352d..e2ffc881b7a 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs @@ -18,7 +18,7 @@ public partial class CallReducer [DataMember(Name = "reducer")] public string Reducer; [DataMember(Name = "args")] - public byte[] Args; + public System.Collections.Generic.List Args; [DataMember(Name = "request_id")] public uint RequestId; [DataMember(Name = "flags")] @@ -26,7 +26,7 @@ public partial class CallReducer public CallReducer( string Reducer, - byte[] Args, + System.Collections.Generic.List Args, uint RequestId, byte Flags ) @@ -40,7 +40,7 @@ byte Flags public CallReducer() { this.Reducer = ""; - this.Args = Array.Empty(); + this.Args = new(); } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs index 9cb1c4c7374..d35135f95c4 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs @@ -13,6 +13,8 @@ namespace SpacetimeDB.ClientApi public partial record ClientMessage : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.CallReducer CallReducer, SpacetimeDB.ClientApi.Subscribe Subscribe, - SpacetimeDB.ClientApi.OneOffQuery OneOffQuery + SpacetimeDB.ClientApi.OneOffQuery OneOffQuery, + SpacetimeDB.ClientApi.SubscribeSingle SubscribeSingle, + SpacetimeDB.ClientApi.Unsubscribe Unsubscribe )>; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs index 1af6fd27c4f..0fc85f50a49 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs @@ -12,7 +12,7 @@ namespace SpacetimeDB.ClientApi [SpacetimeDB.Type] public partial record CompressableQueryUpdate : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.QueryUpdate Uncompressed, - byte[] Brotli, - byte[] Gzip + System.Collections.Generic.List Brotli, + System.Collections.Generic.List Gzip )>; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs index 98460753484..7b28c94be99 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs @@ -18,9 +18,7 @@ public partial class DatabaseUpdate [DataMember(Name = "tables")] public System.Collections.Generic.List Tables; - public DatabaseUpdate( - System.Collections.Generic.List Tables - ) + public DatabaseUpdate(System.Collections.Generic.List Tables) { this.Tables = Tables; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs index e571a9e1e6b..e38a46b5bbc 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs @@ -18,9 +18,7 @@ public partial class EnergyQuanta [DataMember(Name = "quanta")] public U128 Quanta; - public EnergyQuanta( - U128 Quanta - ) + public EnergyQuanta(U128 Quanta) { this.Quanta = Quanta; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs index 11370a540d7..58766dedad8 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs @@ -16,12 +16,12 @@ namespace SpacetimeDB.ClientApi public partial class OneOffQuery { [DataMember(Name = "message_id")] - public byte[] MessageId; + public System.Collections.Generic.List MessageId; [DataMember(Name = "query_string")] public string QueryString; public OneOffQuery( - byte[] MessageId, + System.Collections.Generic.List MessageId, string QueryString ) { @@ -31,7 +31,7 @@ string QueryString public OneOffQuery() { - this.MessageId = Array.Empty(); + this.MessageId = new(); this.QueryString = ""; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs index 2bdb8e1ad0c..a39b3fe1ae7 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs @@ -16,7 +16,7 @@ namespace SpacetimeDB.ClientApi public partial class OneOffQueryResponse { [DataMember(Name = "message_id")] - public byte[] MessageId; + public System.Collections.Generic.List MessageId; [DataMember(Name = "error")] public string? Error; [DataMember(Name = "tables")] @@ -25,7 +25,7 @@ public partial class OneOffQueryResponse public ulong TotalHostExecutionDurationMicros; public OneOffQueryResponse( - byte[] MessageId, + System.Collections.Generic.List MessageId, string? Error, System.Collections.Generic.List Tables, ulong TotalHostExecutionDurationMicros @@ -39,7 +39,7 @@ ulong TotalHostExecutionDurationMicros public OneOffQueryResponse() { - this.MessageId = Array.Empty(); + this.MessageId = new(); this.Tables = new(); } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs new file mode 100644 index 00000000000..07ca5419af6 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs @@ -0,0 +1,31 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class QueryId + { + [DataMember(Name = "id")] + public uint Id; + + public QueryId(uint Id) + { + this.Id = Id; + } + + public QueryId() + { + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs.meta new file mode 100644 index 00000000000..392536c1eac --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5839c57344b5d64e74c4564ffb7d92f7 +MonoImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs index f8acaffd411..ba12f153405 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs @@ -20,14 +20,14 @@ public partial class ReducerCallInfo [DataMember(Name = "reducer_id")] public uint ReducerId; [DataMember(Name = "args")] - public byte[] Args; + public System.Collections.Generic.List Args; [DataMember(Name = "request_id")] public uint RequestId; public ReducerCallInfo( string ReducerName, uint ReducerId, - byte[] Args, + System.Collections.Generic.List Args, uint RequestId ) { @@ -40,7 +40,7 @@ uint RequestId public ReducerCallInfo() { this.ReducerName = ""; - this.Args = Array.Empty(); + this.Args = new(); } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs index f66fdd98347..bcab7a7670a 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs @@ -15,6 +15,9 @@ public partial record ServerMessage : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.TransactionUpdate TransactionUpdate, SpacetimeDB.ClientApi.TransactionUpdateLight TransactionUpdateLight, SpacetimeDB.ClientApi.IdentityToken IdentityToken, - SpacetimeDB.ClientApi.OneOffQueryResponse OneOffQueryResponse + SpacetimeDB.ClientApi.OneOffQueryResponse OneOffQueryResponse, + SpacetimeDB.ClientApi.SubscribeApplied SubscribeApplied, + SpacetimeDB.ClientApi.UnsubscribeApplied UnsubscribeApplied, + SpacetimeDB.ClientApi.SubscriptionError SubscriptionError )>; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs new file mode 100644 index 00000000000..440ef4ca0b1 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class SubscribeApplied + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "query_id")] + public SpacetimeDB.ClientApi.QueryId QueryId; + [DataMember(Name = "rows")] + public SpacetimeDB.ClientApi.SubscribeRows Rows; + + public SubscribeApplied( + uint RequestId, + ulong TotalHostExecutionDurationMicros, + SpacetimeDB.ClientApi.QueryId QueryId, + SpacetimeDB.ClientApi.SubscribeRows Rows + ) + { + this.RequestId = RequestId; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.QueryId = QueryId; + this.Rows = Rows; + } + + public SubscribeApplied() + { + this.QueryId = new(); + this.Rows = new(); + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs.meta new file mode 100644 index 00000000000..b343d062d18 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c99e14f23b6036cd7de97be2069db72e +MonoImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs new file mode 100644 index 00000000000..dffee90c4ea --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs @@ -0,0 +1,43 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class SubscribeRows + { + [DataMember(Name = "table_id")] + public uint TableId; + [DataMember(Name = "table_name")] + public string TableName; + [DataMember(Name = "table_rows")] + public SpacetimeDB.ClientApi.TableUpdate TableRows; + + public SubscribeRows( + uint TableId, + string TableName, + SpacetimeDB.ClientApi.TableUpdate TableRows + ) + { + this.TableId = TableId; + this.TableName = TableName; + this.TableRows = TableRows; + } + + public SubscribeRows() + { + this.TableName = ""; + this.TableRows = new(); + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs.meta new file mode 100644 index 00000000000..378eac7159d --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a92d1b128da222eb02e454367e4975b +MonoImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs new file mode 100644 index 00000000000..5df6f3d7a3b --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs @@ -0,0 +1,43 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class SubscribeSingle + { + [DataMember(Name = "query")] + public string Query; + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "query_id")] + public SpacetimeDB.ClientApi.QueryId QueryId; + + public SubscribeSingle( + string Query, + uint RequestId, + SpacetimeDB.ClientApi.QueryId QueryId + ) + { + this.Query = Query; + this.RequestId = RequestId; + this.QueryId = QueryId; + } + + public SubscribeSingle() + { + this.Query = ""; + this.QueryId = new(); + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs.meta new file mode 100644 index 00000000000..73c9c34fe2c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c60bb4c52fbbd0232497865777d0d702 +MonoImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs new file mode 100644 index 00000000000..f6783fda5d7 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs @@ -0,0 +1,46 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class SubscriptionError + { + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "request_id")] + public uint? RequestId; + [DataMember(Name = "table_id")] + public uint? TableId; + [DataMember(Name = "error")] + public string Error; + + public SubscriptionError( + ulong TotalHostExecutionDurationMicros, + uint? RequestId, + uint? TableId, + string Error + ) + { + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.RequestId = RequestId; + this.TableId = TableId; + this.Error = Error; + } + + public SubscriptionError() + { + this.Error = ""; + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs.meta new file mode 100644 index 00000000000..fba50ff6816 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ddffc0192386ada178b6d140274dfc8 +MonoImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs index 92bd242d50a..27cfa7da95d 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs @@ -18,9 +18,7 @@ public partial class Timestamp [DataMember(Name = "microseconds")] public ulong Microseconds; - public Timestamp( - ulong Microseconds - ) + public Timestamp(ulong Microseconds) { this.Microseconds = Microseconds; } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs new file mode 100644 index 00000000000..b6fe8d01c4f --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs @@ -0,0 +1,38 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class Unsubscribe + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "query_id")] + public SpacetimeDB.ClientApi.QueryId QueryId; + + public Unsubscribe( + uint RequestId, + SpacetimeDB.ClientApi.QueryId QueryId + ) + { + this.RequestId = RequestId; + this.QueryId = QueryId; + } + + public Unsubscribe() + { + this.QueryId = new(); + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs.meta new file mode 100644 index 00000000000..c825ecddb7a --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afdaf1dde5b73fdb44b7b0e967166a43 +MonoImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs new file mode 100644 index 00000000000..26832e7cf87 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class UnsubscribeApplied + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "query_id")] + public SpacetimeDB.ClientApi.QueryId QueryId; + [DataMember(Name = "rows")] + public SpacetimeDB.ClientApi.SubscribeRows Rows; + + public UnsubscribeApplied( + uint RequestId, + ulong TotalHostExecutionDurationMicros, + SpacetimeDB.ClientApi.QueryId QueryId, + SpacetimeDB.ClientApi.SubscribeRows Rows + ) + { + this.RequestId = RequestId; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.QueryId = QueryId; + this.Rows = Rows; + } + + public UnsubscribeApplied() + { + this.QueryId = new(); + this.Rows = new(); + } + + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs.meta new file mode 100644 index 00000000000..668cf4783d3 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a958bf68ea209aafda05cf9222cb3639 +MonoImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 6e22eb7700e..71408529c7c 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -241,100 +241,75 @@ enum CompressionAlgos : byte Gzip = 2, } - private static BinaryReader BrotliReader(Stream stream) + private static BrotliStream BrotliReader(Stream stream) { - return new BinaryReader(new BrotliStream(stream, CompressionMode.Decompress)); + return new BrotliStream(stream, CompressionMode.Decompress); } - private static BinaryReader GzipReader(Stream stream) + private static GZipStream GzipReader(Stream stream) { - return new BinaryReader(new GZipStream(stream, CompressionMode.Decompress)); + return new GZipStream(stream, CompressionMode.Decompress); } private static ServerMessage DecompressDecodeMessage(byte[] bytes) { - using var stream = new MemoryStream(bytes, 1, bytes.Length - 1); + using var stream = new MemoryStream(bytes); // The stream will never be empty. It will at least contain the compression algo. - var compression = (CompressionAlgos)bytes[0]; + var compression = (CompressionAlgos)stream.ReadByte(); // Conditionally decompress and decode. - switch (compression) + Stream decompressedStream = compression switch { - case CompressionAlgos.None: - return new ServerMessage.BSATN().Read(new BinaryReader(stream)); - case CompressionAlgos.Brotli: - return new ServerMessage.BSATN().Read(BrotliReader(stream)); - case CompressionAlgos.Gzip: - return new ServerMessage.BSATN().Read(GzipReader(stream)); - default: - throw new InvalidOperationException("Unknown compression type"); - } + CompressionAlgos.None => stream, + CompressionAlgos.Brotli => BrotliReader(stream), + CompressionAlgos.Gzip => GzipReader(stream), + _ => throw new InvalidOperationException("Unknown compression type"), + }; + + return new ServerMessage.BSATN().Read(new BinaryReader(decompressedStream)); } private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate update) { + Stream decompressedStream; + switch (update) { case CompressableQueryUpdate.Uncompressed(var qu): return qu; case CompressableQueryUpdate.Brotli(var bytes): - return new QueryUpdate.BSATN().Read(BrotliReader(new MemoryStream(bytes))); + decompressedStream = BrotliReader(new MemoryStream(bytes.ToArray())); + break; case CompressableQueryUpdate.Gzip(var bytes): - return new QueryUpdate.BSATN().Read(GzipReader(new MemoryStream(bytes))); + decompressedStream = GzipReader(new MemoryStream(bytes.ToArray())); + break; default: throw new InvalidOperationException(); } - } - private static int BsatnRowListCount(BsatnRowList list) - { - switch (list.SizeHint) - { - case RowSizeHint.FixedSize(var size): - return list.RowsData.Length / size; - case RowSizeHint.RowOffsets(var offsets): - return offsets.Count; - default: - throw new InvalidOperationException("Unknown RowSizeHint variant"); - } + return new QueryUpdate.BSATN().Read(new BinaryReader(decompressedStream)); } private static IEnumerable BsatnRowListIter(BsatnRowList list) { - var count = BsatnRowListCount(list); - for (int index = 0; index < count; index += 1) + var rowsData = list.RowsData; + + return list.SizeHint switch { - switch (list.SizeHint) - { - case RowSizeHint.FixedSize(var size): - { - int start = index * size; - int elemLen = size; - yield return new ReadOnlySpan(list.RowsData, start, elemLen).ToArray(); - break; - } - case RowSizeHint.RowOffsets(var offsets): - { - int start = (int)offsets[index]; - // The end is either the start of the next element or the end. - int end; - if (index + 1 == count) - { - end = list.RowsData.Length; - } - else - { - end = (int)offsets[index + 1]; - } - int elemLen = end - start; - yield return new ReadOnlyMemory(list.RowsData, start, elemLen).ToArray(); - break; - } - } - } + RowSizeHint.FixedSize(var size) => Enumerable + .Range(0, rowsData.Count / size) + .Select(index => rowsData.Skip(index * size).Take(size).ToArray()), + + RowSizeHint.RowOffsets(var offsets) => offsets.Zip( + offsets.Skip(1).Append((ulong)rowsData.Count), + (start, end) => rowsData.Take((int)end).Skip((int)start).ToArray() + ), + + _ => throw new InvalidOperationException("Unknown RowSizeHint variant"), + }; } void PreProcessMessages() @@ -398,7 +373,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) foreach (var cqu in update.Updates) { var qu = DecompressDecodeQueryUpdate(cqu); - if (BsatnRowListCount(qu.Deletes) != 0) + if (qu.Deletes.RowsData.Count > 0) { Log.Warn("Non-insert during a subscription update!"); } @@ -520,7 +495,7 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) void PreProcessOneOffQuery(OneOffQueryResponse resp) { /// This case does NOT produce a list of DBOps, because it should not modify the client cache state! - var messageId = new Guid(resp.MessageId); + var messageId = new Guid(resp.MessageId.ToArray()); if (!waitingOneOffQueries.Remove(messageId, out var resultSource)) { @@ -883,7 +858,7 @@ public void InternalCallReducer(T args, CallReducerFlags flags) webSocket.Send(new ClientMessage.CallReducer(new CallReducer( args.ReducerName, - IStructuralReadWrite.ToBytes(args), + IStructuralReadWrite.ToBytes(args).ToList(), stats.ReducerRequestTracker.StartTrackingRequest(args.ReducerName), (byte)flags ))); @@ -925,7 +900,7 @@ async Task IDbConnection.RemoteQuery(string query) var requestId = stats.OneOffRequestTracker.StartTrackingRequest(); webSocket.Send(new ClientMessage.OneOffQuery(new OneOffQuery { - MessageId = messageId.ToByteArray(), + MessageId = messageId.ToByteArray().ToList(), QueryString = query, })); @@ -964,7 +939,7 @@ T[] LogAndThrow(string error) } return BsatnRowListIter(resultTable.Rows) - .Select(row => BSATNHelpers.Decode(row)) + .Select(BSATNHelpers.Decode) .ToArray(); } diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index d57379b5270..6b0bc77bf44 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -142,7 +142,7 @@ private static ServerMessage.TransactionUpdate SampleTransactionUpdate( { RequestId = requestId, ReducerName = reducerName, - Args = args ?? [] + Args = [.. (args ?? [])] }, Status = new UpdateStatus.Committed(new() { @@ -176,7 +176,7 @@ private static BsatnRowList EncodeRowList(in List list) where T : IStructu } return new BsatnRowList { - RowsData = stream.ToArray(), + RowsData = stream.ToArray().ToList(), SizeHint = new RowSizeHint.RowOffsets(offsets) }; } diff --git a/sdks/csharp/tools~/gen-client-api.sh b/sdks/csharp/tools~/gen-client-api.sh index 5f118176a08..a34fd0d6630 100755 --- a/sdks/csharp/tools~/gen-client-api.sh +++ b/sdks/csharp/tools~/gen-client-api.sh @@ -1,15 +1,11 @@ -#!/bin/sh -eu -: $CL_HOME +set -ueo pipefail -cd $CL_HOME/SpacetimeDB/crates/client-api-messages -cargo run --example get_ws_schema > $CL_HOME/schema.json +STDB_PATH="$1" +SDK_PATH="$(dirname "$0")/.." -cd $CL_HOME/SpacetimeDB/crates/cli -cargo run -- generate -l csharp --namespace SpacetimeDB.ClientApi \ - --module-def $CL_HOME/schema.json \ - -o $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi +cargo run --manifest-path $STDB_PATH/crates/client-api-messages/Cargo.toml --example get_ws_schema | +cargo run --manifest-path $STDB_PATH/crates/cli/Cargo.toml -- generate -l csharp --namespace SpacetimeDB.ClientApi \ + --module-def \ + -o $SDK_PATH/src/SpacetimeDB/ClientApi -cd $CL_HOME/spacetimedb-csharp-sdk/src/SpacetimeDB/ClientApi -rm -rf _Globals - -rm -f $CL_HOME/schema.json +rm -rf $SDK_PATH/src/SpacetimeDB/ClientApi/_Globals From 62e16c6333b49aca43ae19a6a90a573f756df971 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 23 Jan 2025 15:40:38 +0000 Subject: [PATCH 162/223] Unify CI handling of SpacetimeDB branch (#215) ## Description of Changes This unifies various CI task into a single config that checks out the referenced SpacetimeDB branch only once and using the same PR parsing code (previously used only in Unity), and then runs all the builds and tests against it. That is, .NET test, server module and Unity tests are now all consistently overridden to point to the same SpacetimeDB. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing - [x] Lots of CI testing and tweaking until all of existing CI tests started working again; ensured .NET tests are executed as expected against the specified branch name. --- sdks/csharp/.github/workflows/dotnet.yml | 53 ------ sdks/csharp/.github/workflows/test.yml | 154 ++++++++++++++++++ sdks/csharp/.github/workflows/unity-test.yml | 150 ----------------- .../workflows/unity-testsuite-bindings.yml | 115 ------------- 4 files changed, 154 insertions(+), 318 deletions(-) delete mode 100644 sdks/csharp/.github/workflows/dotnet.yml create mode 100644 sdks/csharp/.github/workflows/test.yml delete mode 100644 sdks/csharp/.github/workflows/unity-test.yml delete mode 100644 sdks/csharp/.github/workflows/unity-testsuite-bindings.yml diff --git a/sdks/csharp/.github/workflows/dotnet.yml b/sdks/csharp/.github/workflows/dotnet.yml deleted file mode 100644 index 40dbd7ab9d7..00000000000 --- a/sdks/csharp/.github/workflows/dotnet.yml +++ /dev/null @@ -1,53 +0,0 @@ -# This workflow will build a .NET project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net - -name: .NET build - -on: - push: - pull_request: - types: [opened, reopened] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - path: spacetimedb-csharp-sdk - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - name: Checkout SpacetimeDB - uses: actions/checkout@v4 - with: - repository: clockworklabs/SpacetimeDB - path: SpacetimeDB - - name: Setup SpacetimeDB packages - working-directory: spacetimedb-csharp-sdk - run: | - dotnet pack ../SpacetimeDB/crates/bindings-csharp/BSATN.Runtime - - # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository - # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if - # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. - # This means that (if version numbers match) we will test the local versions of the C# packages, even - # if they're not pushed to NuGet. - # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. - ./tools~/write-nuget-config.sh ../SpacetimeDB - - - name: Restore dependencies - working-directory: spacetimedb-csharp-sdk - run: dotnet restore - - name: Build everything - working-directory: spacetimedb-csharp-sdk - run: dotnet build --no-restore -warnaserror - - name: Run tests - working-directory: spacetimedb-csharp-sdk - run: dotnet test --no-build - - name: Verify formatting - working-directory: spacetimedb-csharp-sdk - run: dotnet format --no-restore --verify-no-changes SpacetimeDB.ClientSDK.sln diff --git a/sdks/csharp/.github/workflows/test.yml b/sdks/csharp/.github/workflows/test.yml new file mode 100644 index 00000000000..ba368d7c471 --- /dev/null +++ b/sdks/csharp/.github/workflows/test.yml @@ -0,0 +1,154 @@ +name: Test Suite + +on: + push: + branches: + - staging + pull_request: + +jobs: + unity-testsuite: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: true + + # Grab the SpacetimeDB branch name from the PR description. If it's not found, master will be used instead. + # We'll use this branch name for any integration tests with SpacetimeDB. + + - name: Extract SpacetimeDB branch name or PR link from PR description + id: extract-branch + if: github.event_name == 'pull_request' + env: + description: ${{ github.event.pull_request.body }} + run: | + # Check if description contains a branch name or a PR link + branch_or_pr=$(echo "$description" | grep -oP '(?<=SpacetimeDB branch name:\s).+') + echo "Branch or PR found: $branch_or_pr" + + if [[ -z "$branch_or_pr" ]]; then + branch="master" + elif [[ "$branch_or_pr" =~ ^https://github.com/.*/pull/[0-9]+$ ]]; then + # If it's a PR link, extract the branch name from the PR + pr_number=$(echo "$branch_or_pr" | grep -oP '[0-9]+$') + branch=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + https://api.github.com/repos/clockworklabs/SpacetimeDB/pulls/$pr_number | jq -r '.head.ref') + else + # It's already a branch name + branch="$branch_or_pr" + fi + + echo "branch=$branch" >> $GITHUB_OUTPUT + echo "Final branch name: $branch" + + - name: Checkout SpacetimeDB + uses: actions/checkout@v4 + with: + repository: clockworklabs/SpacetimeDB + ref: ${{ steps.extract-branch.outputs.branch }} + path: SpacetimeDB~ + + # Run cheap .NET tests first. If those fail, no need to run expensive Unity tests. + + - name: Override NuGet packages + run: | + dotnet pack SpacetimeDB~/crates/bindings-csharp/BSATN.Runtime + + # Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository + # to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if + # available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages. + # This means that (if version numbers match) we will test the local versions of the C# packages, even + # if they're not pushed to NuGet. + # See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file. + ./tools~/write-nuget-config.sh SpacetimeDB~ + + - name: Run .NET tests + run: dotnet test -warnaserror + + - name: Verify C# formatting + run: dotnet format --no-restore --verify-no-changes SpacetimeDB.ClientSDK.sln + + # Now, setup the Unity tests. + + - name: Patch spacetimedb dependency in Cargo.toml + working-directory: unity-tests~/server + run: | + sed -i "s|spacetimedb *=.*|spacetimedb = \{ path = \"../../SpacetimeDB~/crates/bindings\" \}|" Cargo.toml + cat Cargo.toml + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 + with: + workspaces: unity-tests~/server + shared-key: UnityTestServer + + - name: Install SpacetimeDB CLI from the local checkout + run: | + cargo install --path SpacetimeDB~/crates/cli --locked --message-format=short + cargo install --path SpacetimeDB~/crates/standalone --locked --message-format=short + # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). + ln -s $HOME/.cargo/bin/spacetimedb-cli $HOME/.cargo/bin/spacetime + env: + # Share the target directory with our local project to avoid rebuilding same SpacetimeDB crates twice. + CARGO_TARGET_DIR: unity-tests~/server/target + + - name: Generate client bindings + working-directory: unity-tests~/server + run: bash ./generate.sh -y + + - name: Check for changes + run: | + git diff --exit-code unity-tests~/client/Assets/Scripts/autogen || { + echo "Error: Bindings are dirty. Please generate bindings again and commit them to this branch." + exit 1 + } + + - name: Check Unity meta files + uses: DeNA/unity-meta-check@v3 + with: + enable_pr_comment: ${{ github.event_name == 'pull_request' }} + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + - name: Start SpacetimeDB + run: | + spacetime start & + disown + + - name: Publish module to SpacetimeDB + working-directory: unity-tests~/server + run: bash ./publish.sh + + - uses: actions/cache@v3 + with: + path: unity-tests~/client/Library + key: Library-SpacetimeDBUnityTestsuite-Linux-x86 + restore-keys: | + Library-SpacetimeDBUnityTestsuite- + Library- + + - name: Patch com.clockworklabs.spacetimedbsdk dependency in manifest.json + working-directory: unity-tests~/client/Packages + run: | + # Replace the com.clockworklabs.spacetimedbsdk dependency with the current branch. + # TODO: find out why pointing to a local directory doesn't work - is it because Unity CI action uses Docker? + yq e -i '.dependencies["com.clockworklabs.spacetimedbsdk"] = "https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk.git#${{ github.head_ref }}"' manifest.json + cat manifest.json + + - name: Run Unity tests + uses: game-ci/unity-test-runner@v4 + with: + unityVersion: 2022.3.32f1 # Adjust Unity version to a valid tag + projectPath: unity-tests~/client # Path to the Unity project subdirectory + githubToken: ${{ secrets.GITHUB_TOKEN }} + testMode: playmode + useHostNetwork: true + env: + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} diff --git a/sdks/csharp/.github/workflows/unity-test.yml b/sdks/csharp/.github/workflows/unity-test.yml deleted file mode 100644 index 44ae050f1be..00000000000 --- a/sdks/csharp/.github/workflows/unity-test.yml +++ /dev/null @@ -1,150 +0,0 @@ -name: Unity Test Suite - -on: - push: - branches: - - staging - pull_request: - -jobs: - unity-testsuite: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: true - - - name: Check Unity meta files - uses: DeNA/unity-meta-check@v3 - with: - enable_pr_comment: ${{ github.event_name == 'pull_request' }} - env: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - - # Grab the branch name from the PR description. If it's not found, master will be used instead. - - name: Extract SpacetimeDB branch name or PR link from PR description - id: extract-branch - if: github.event_name == 'pull_request' - env: - description: ${{ github.event.pull_request.body }} - run: | - # Check if description contains a branch name or a PR link - branch_or_pr=$(echo "$description" | grep -oP '(?<=SpacetimeDB branch name:\s).+') - echo "Branch or PR found: $branch_or_pr" - - if [[ -z "$branch_or_pr" ]]; then - branch="master" - elif [[ "$branch_or_pr" =~ ^https://github.com/.*/pull/[0-9]+$ ]]; then - # If it's a PR link, extract the branch name from the PR - pr_number=$(echo "$branch_or_pr" | grep -oP '[0-9]+$') - branch=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - https://api.github.com/repos/clockworklabs/SpacetimeDB/pulls/$pr_number | jq -r '.head.ref') - else - # It's already a branch name - branch="$branch_or_pr" - fi - - echo "branch=$branch" >> $GITHUB_OUTPUT - echo "Final branch name: $branch" - - - name: Replace com.clockworklabs.spacetimedbsdk in manifest.json - run: | - # Get the branch name from the environment variable - branch_name="${{ github.head_ref }}" - # Replace any reference to com.clockworklabs.spacetimedbsdk with the correct GitHub URL using the current branch - sed -i "s|\"com.clockworklabs.spacetimedbsdk\":.*|\"com.clockworklabs.spacetimedbsdk\": \"https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk.git#$branch_name\",|" unity-tests~/client/Packages/manifest.json - cat unity-tests~/client/Packages/manifest.json - - - name: Replace spacetimedb dependency in Cargo.toml - run: | - # Get the branch name from the environment variable - branch_name="${{ github.head_ref }}" - # Make sure we're using the correct bindings when building the module TODO - sed -i "s|spacetimedb.*=.*|spacetimedb = \{ path = \"../SpacetimeDB/crates/bindings\" \}|" unity-tests~/server/Cargo.toml - cat unity-tests~/server/Cargo.toml - - name: Install Rust toolchain - run: | - curl https://sh.rustup.rs -sSf | sh -s -- -y - source $HOME/.cargo/env - rustup install stable - rustup default stable - - - name: Cache Cargo target directory - uses: actions/cache@v3 - with: - path: unity-tests~/server/target - key: server-target-SpacetimeDBUnityTestsuite-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} - restore-keys: | - server-target-SpacetimeDBUnityTestsuite-${{ runner.os }}-${{ runner.arch }}- - server-target-SpacetimeDBUnityTestsuite- - - - name: Cache Cargo registry - uses: actions/cache@v3 - with: - path: ~/.cargo/registry - key: cargo-registry-${{ runner.os }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} - restore-keys: | - cargo-registry-${{ runner.os }}- - cargo-registry- - - - name: Cache Cargo index - uses: actions/cache@v3 - with: - path: ~/.cargo/git - key: cargo-index-${{ runner.os }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} - restore-keys: | - cargo-index-${{ runner.os }}- - cargo-index- - - - name: Install SpacetimeDB CLI from specific branch - run: | - cd unity-tests~ - git clone https://github.com/clockworklabs/SpacetimeDB.git - cd SpacetimeDB - # Sanitize the branch name by trimming any newlines or spaces - branch_name=$(echo "${{ steps.extract-branch.outputs.branch }}" | tr -d '[:space:]') - # If the branch name is not found, default to master - if [ -z "$branch_name" ]; then - branch_name="master" - fi - git checkout "$branch_name" - echo "Checked out branch: $branch_name" - cargo build --release -p spacetimedb-cli - sudo mv target/release/spacetime /usr/bin/spacetime - - - name: Generate client bindings - run: | - cd unity-tests~/server - bash ./generate.sh -y - - - name: Start SpacetimeDB - run: | - spacetime start & - disown - - - name: Publish module to SpacetimeDB - run: | - cd unity-tests~/server - bash ./publish.sh - - - uses: actions/cache@v3 - with: - path: unity-tests~/client/Library - key: Library-SpacetimeDBUnityTestsuite-Linux-x86 - restore-keys: | - Library-SpacetimeDBUnityTestsuite- - Library- - - - name: Set up Unity - uses: game-ci/unity-test-runner@v4 - with: - unityVersion: 2022.3.32f1 # Adjust Unity version to a valid tag - projectPath: unity-tests~/client # Path to the Unity project subdirectory - githubToken: ${{ secrets.GITHUB_TOKEN }} - testMode: playmode - useHostNetwork: true - env: - UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} - UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} - UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} diff --git a/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml b/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml deleted file mode 100644 index 71a6090a8ea..00000000000 --- a/sdks/csharp/.github/workflows/unity-testsuite-bindings.yml +++ /dev/null @@ -1,115 +0,0 @@ -name: Check Unity Testsuite Bindings - -on: - push: - branches: - - staging - pull_request: - -jobs: - check-testsuite-bindings: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: true - - # Grab the branch name from the PR description. If it's not found, master will be used instead. - - name: Extract SpacetimeDB branch name or PR link from PR description - id: extract-branch - if: github.event_name == 'pull_request' - env: - description: ${{ github.event.pull_request.body }} - run: | - # Check if description contains a branch name or a PR link - branch_or_pr=$(echo "$description" | grep -oP '(?<=SpacetimeDB branch name:\s).+') - echo "Branch or PR found: $branch_or_pr" - - if [[ -z "$branch_or_pr" ]]; then - branch="master" - elif [[ "$branch_or_pr" =~ ^https://github.com/.*/pull/[0-9]+$ ]]; then - # If it's a PR link, extract the branch name from the PR - pr_number=$(echo "$branch_or_pr" | grep -oP '[0-9]+$') - branch=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - https://api.github.com/repos/clockworklabs/SpacetimeDB/pulls/$pr_number | jq -r '.head.ref') - else - # It's already a branch name - branch="$branch_or_pr" - fi - - echo "branch=$branch" >> $GITHUB_OUTPUT - echo "Final branch name: $branch" - - - name: Replace spacetimedb dependency in Cargo.toml - run: | - # Get the branch name from the environment variable - branch_name="${{ github.head_ref }}" - # Make sure we're using the correct bindings when building the module TODO - sed -i "s|spacetimedb.*=.*|spacetimedb = \{ path = \"../SpacetimeDB/crates/bindings\" \}|" unity-tests~/server/Cargo.toml - cat unity-tests~/server/Cargo.toml - - name: Install Rust toolchain - run: | - curl https://sh.rustup.rs -sSf | sh -s -- -y - source $HOME/.cargo/env - rustup install stable - rustup default stable - - - name: Cache Cargo target directory - uses: actions/cache@v3 - with: - path: unity-tests~/server/target - key: server-target-SpacetimeDBUnityTestsuite-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} - restore-keys: | - server-target-SpacetimeDBUnityTestsuite-${{ runner.os }}-${{ runner.arch }}- - server-target-SpacetimeDBUnityTestsuite- - - - name: Cache Cargo registry - uses: actions/cache@v3 - with: - path: ~/.cargo/registry - key: cargo-registry-${{ runner.os }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} - restore-keys: | - cargo-registry-${{ runner.os }}- - cargo-registry- - - - name: Cache Cargo index - uses: actions/cache@v3 - with: - path: ~/.cargo/git - key: cargo-index-${{ runner.os }}-${{ hashFiles('unity-tests~/server/Cargo.lock') }} - restore-keys: | - cargo-index-${{ runner.os }}- - cargo-index- - - - name: Install SpacetimeDB CLI from specific branch - run: | - cd unity-tests~ - git clone https://github.com/clockworklabs/SpacetimeDB.git - cd SpacetimeDB - # Sanitize the branch name by trimming any newlines or spaces - branch_name=$(echo "${{ steps.extract-branch.outputs.branch }}" | tr -d '[:space:]') - # If the branch name is not found, default to master - if [ -z "$branch_name" ]; then - branch_name="master" - fi - git checkout "$branch_name" - echo "Checked out branch: $branch_name" - cargo build --release -p spacetimedb-cli - sudo mv target/release/spacetime /usr/bin/spacetime - - - name: Generate client bindings - run: | - cd unity-tests~/server - bash ./generate.sh -y - - - name: Check for changes - run: | - git diff --exit-code unity-tests~/client/Assets/Scripts/autogen - continue-on-error: true - - - name: Fail if there are changes - if: ${{ steps.check-for-changes.outcome == 'failure' }} - run: | - echo "Error: Bindings are dirty. Please generate bindings again and commit them to this branch." - exit 1 From 6578f0563bbd14e5396674e9b8b7d5eef7d82c6a Mon Sep 17 00:00:00 2001 From: james gilles Date: Thu, 23 Jan 2025 16:22:29 -0500 Subject: [PATCH 163/223] Implement new subscription API (#219) ## Description of Changes As proposed. No upstream codegen changes needed :) ## API - [x] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* The subscription API is slightly different. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2111 ## Testsuite SpacetimeDB branch name: jsdt/subscribe-sdk-3 ## Testing So far I have performed manual testing with the chat example. Working on updating the unity and unit tests. - [ ] Describe a test for this PR that you have completed --- sdks/csharp/.github/workflows/test.yml | 17 +- .../examples~/quickstart/client/Program.cs | 28 +- sdks/csharp/src/Event.cs | 151 ++++- .../ClientApi/SubscriptionError.cs | 4 + sdks/csharp/src/SpacetimeDBClient.cs | 290 +++++++-- ..._dumpName=LegacySubscribeAll.verified.txt} | 18 +- ...ump_dumpName=SubscribeApplied.verified.txt | 558 ++++++++++++++++++ sdks/csharp/tests~/SnapshotTests.cs | 298 +++++++--- sdks/csharp/tests~/VerifyInit.cs | 9 +- sdks/csharp/unity-tests~ | 2 +- 10 files changed, 1219 insertions(+), 156 deletions(-) rename sdks/csharp/tests~/{SnapshotTests.VerifyAllTablesParsed.verified.txt => SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt} (94%) create mode 100644 sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt diff --git a/sdks/csharp/.github/workflows/test.yml b/sdks/csharp/.github/workflows/test.yml index ba368d7c471..84d3c552bdd 100644 --- a/sdks/csharp/.github/workflows/test.yml +++ b/sdks/csharp/.github/workflows/test.yml @@ -73,7 +73,7 @@ jobs: # Now, setup the Unity tests. - name: Patch spacetimedb dependency in Cargo.toml - working-directory: unity-tests~/server + working-directory: unity-tests~/server-rust run: | sed -i "s|spacetimedb *=.*|spacetimedb = \{ path = \"../../SpacetimeDB~/crates/bindings\" \}|" Cargo.toml cat Cargo.toml @@ -84,7 +84,7 @@ jobs: - name: Cache Rust dependencies uses: Swatinem/rust-cache@v2 with: - workspaces: unity-tests~/server + workspaces: unity-tests~/server-rust shared-key: UnityTestServer - name: Install SpacetimeDB CLI from the local checkout @@ -92,13 +92,16 @@ jobs: cargo install --path SpacetimeDB~/crates/cli --locked --message-format=short cargo install --path SpacetimeDB~/crates/standalone --locked --message-format=short # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). + rm $HOME/.cargo/bin/spacetime || echo "haven't run on this host before" ln -s $HOME/.cargo/bin/spacetimedb-cli $HOME/.cargo/bin/spacetime + # Clear any existing information + spacetime server clear -y env: # Share the target directory with our local project to avoid rebuilding same SpacetimeDB crates twice. - CARGO_TARGET_DIR: unity-tests~/server/target + CARGO_TARGET_DIR: unity-tests~/server-rust/target - name: Generate client bindings - working-directory: unity-tests~/server + working-directory: unity-tests~/server-rust run: bash ./generate.sh -y - name: Check for changes @@ -121,8 +124,10 @@ jobs: disown - name: Publish module to SpacetimeDB - working-directory: unity-tests~/server - run: bash ./publish.sh + working-directory: unity-tests~/server-rust + run: | + spacetime logout && spacetime login --server-issued-login local + bash ./publish.sh - uses: actions/cache@v3 with: diff --git a/sdks/csharp/examples~/quickstart/client/Program.cs b/sdks/csharp/examples~/quickstart/client/Program.cs index 9eb43b13be8..f82d8f87e69 100644 --- a/sdks/csharp/examples~/quickstart/client/Program.cs +++ b/sdks/csharp/examples~/quickstart/client/Program.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Linq; -using System.Net.WebSockets; using System.Threading; using SpacetimeDB; using SpacetimeDB.Types; @@ -135,9 +133,29 @@ void OnConnect(DbConnection conn, Identity identity, string authToken) local_identity = identity; AuthToken.SaveToken(authToken); - conn.SubscriptionBuilder() - .OnApplied(OnSubscriptionApplied) - .Subscribe("SELECT * FROM user", "SELECT * FROM message"); + var subscriptions = 0; + SubscriptionBuilder.Callback waitForSubscriptions = (EventContext ctx) => + { + // Note: callbacks are always invoked on the main thread, so you don't need to + // worry about thread synchronization or anything like that. + subscriptions += 1; + + if (subscriptions == 2) + { + OnSubscriptionApplied(ctx); + } + }; + + var userSubscription = conn.SubscriptionBuilder() + .OnApplied(waitForSubscriptions) + .Subscribe("SELECT * FROM user"); + var messageSubscription = conn.SubscriptionBuilder() + .OnApplied(waitForSubscriptions) + .Subscribe("SELECT * FROM message"); + + // You can also use SubscribeToAllTables, but it should be avoided if you have any large tables: + // conn.SubscriptionBuilder().OnApplied(OnSubscriptionApplied).SubscribeToAllTables(); + } void OnConnectError(Exception e) diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 75f30167350..2f69d43af40 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -1,4 +1,5 @@ using System; +using SpacetimeDB.ClientApi; namespace SpacetimeDB { @@ -62,41 +63,169 @@ public SubscriptionBuilder OnError(Callback callback) return this; } - public SubscriptionHandle Subscribe(params string[] querySqls) => new(conn, Applied, Error, querySqls); + public SubscriptionHandle Subscribe(string querySql) => new(conn, Applied, Error, querySql); public void SubscribeToAllTables() { - Subscribe("SELECT * FROM *"); + // Make sure we use the legacy handle constructor here, even though there's only 1 query. + // We drop the error handler, since it can't be called for legacy subscriptions. + new SubscriptionHandle(conn, Applied, new string[] { "SELECT * FROM *" }); } } public interface ISubscriptionHandle { - void OnApplied(IEventContext ctx); + void OnApplied(IEventContext ctx, SubscriptionAppliedType state); + void OnError(IEventContext ctx); + void OnEnded(IEventContext ctx); } + /// + /// An applied subscription can either be a new-style subscription (with a query ID), + /// or a legacy subscription (no query ID). + /// + [Type] + public partial record SubscriptionAppliedType : TaggedEnum<( + QueryId Active, + Unit LegacyActive)> + { } + + /// + /// State flow chart: + /// + /// | + /// v + /// Pending + /// | | + /// v v + /// Active LegacyActive + /// | + /// v + /// Ended + /// + /// + [Type] + public partial record SubscriptionState : TaggedEnum<( + Unit Pending, + QueryId Active, + Unit LegacyActive, + Unit Ended)> + { } + public class SubscriptionHandle : ISubscriptionHandle where EventContext : IEventContext { + private readonly IDbConnection conn; private readonly SubscriptionBuilder.Callback? onApplied; + private readonly SubscriptionBuilder.Callback? onError; + private SubscriptionBuilder.Callback? onEnded; - void ISubscriptionHandle.OnApplied(IEventContext ctx) + private SubscriptionState state; + + /// + /// Whether the subscription has ended. + /// + public bool IsEnded { - IsActive = true; + get + { + return state is SubscriptionState.Ended; + } + } + + /// + /// Whether the subscription is active. + /// + public bool IsActive + { + get + { + return state is SubscriptionState.Active || state is SubscriptionState.LegacyActive; + } + } + + void ISubscriptionHandle.OnApplied(IEventContext ctx, SubscriptionAppliedType type) + { + if (type is SubscriptionAppliedType.Active active) + { + state = new SubscriptionState.Active(active.Active_); + } + else if (type is SubscriptionAppliedType.LegacyActive) + { + state = new SubscriptionState.LegacyActive(new()); + } onApplied?.Invoke((EventContext)ctx); } - internal SubscriptionHandle(IDbConnection conn, SubscriptionBuilder.Callback? onApplied, SubscriptionBuilder.Callback? onError, string[] querySqls) + void ISubscriptionHandle.OnEnded(IEventContext ctx) + { + state = new SubscriptionState.Ended(new()); + onEnded?.Invoke((EventContext)ctx); + } + + void ISubscriptionHandle.OnError(IEventContext ctx) + { + state = new SubscriptionState.Ended(new()); + onError?.Invoke((EventContext)ctx); + } + + /// + /// TODO: remove this constructor once legacy subscriptions are removed. + /// + /// + /// + /// + /// + internal SubscriptionHandle(IDbConnection conn, SubscriptionBuilder.Callback? onApplied, string[] querySqls) { + state = new SubscriptionState.Pending(new()); + this.conn = conn; this.onApplied = onApplied; - conn.Subscribe(this, querySqls); + conn.LegacySubscribe(this, querySqls); } - public void Unsubscribe() => throw new NotImplementedException(); + /// + /// Construct a subscription handle. + /// + /// + /// + /// + /// + internal SubscriptionHandle(IDbConnection conn, SubscriptionBuilder.Callback? onApplied, SubscriptionBuilder.Callback? onError, string querySql) + { + state = new SubscriptionState.Pending(new()); + this.onApplied = onApplied; + this.onError = onError; + this.conn = conn; + conn.Subscribe(this, querySql); + } - public void UnsuscribeThen(SubscriptionBuilder.Callback onEnd) => throw new NotImplementedException(); + /// + /// Unsubscribe from the query controlled by this subscription handle. + /// + /// Calling this more than once will result in an exception. + /// + public void Unsubscribe() + { + UnsubscribeThen(null); + } - public bool IsEnded => false; - public bool IsActive { get; private set; } + /// + /// Unsubscribe from the query controlled by this subscription handle, + /// and call onEnded when its rows are removed from the client cache. + /// + public void UnsubscribeThen(SubscriptionBuilder.Callback? onEnded) + { + if (state is not SubscriptionState.Active) + { + throw new Exception("Cannot unsubscribe from inactive subscription."); + } + if (onEnded != null) + { + // TODO: should we just log here instead? Do we try not to throw exceptions on the main thread? + throw new Exception("Unsubscribe already called."); + } + this.onEnded = onEnded; + } } } diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs index f6783fda5d7..249f8991452 100644 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs @@ -19,6 +19,8 @@ public partial class SubscriptionError public ulong TotalHostExecutionDurationMicros; [DataMember(Name = "request_id")] public uint? RequestId; + [DataMember(Name = "query_id")] + public uint? QueryId; [DataMember(Name = "table_id")] public uint? TableId; [DataMember(Name = "error")] @@ -27,12 +29,14 @@ public partial class SubscriptionError public SubscriptionError( ulong TotalHostExecutionDurationMicros, uint? RequestId, + uint? QueryId, uint? TableId, string Error ) { this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; this.RequestId = RequestId; + this.QueryId = QueryId; this.TableId = TableId; this.Error = Error; } diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 71408529c7c..5ca2e938494 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -102,7 +102,9 @@ public DbConnectionBuilder OnDisconnect(DisconnectCallbac public interface IDbConnection { - internal void Subscribe(ISubscriptionHandle handle, string[] querySqls); + internal void LegacySubscribe(ISubscriptionHandle handle, string[] querySqls); + internal void Subscribe(ISubscriptionHandle handle, string querySql); + internal void Unsubscribe(QueryId queryId); void FrameTick(); void Disconnect(); @@ -141,8 +143,22 @@ struct DbOp [Obsolete] public event Action? onSendError; + /// + /// Dictionary of legacy subscriptions, keyed by request ID rather than query ID. + /// Only used for `SubscribeToAllTables()`. + /// + private readonly Dictionary legacySubscriptions = new(); + + /// + /// Dictionary of subscriptions, keyed by query ID. + /// private readonly Dictionary subscriptions = new(); + /// + /// Allocates query IDs. + /// + private UintAllocator queryIdAllocator; + /// /// Invoked when a reducer is returned with an error and has no client-side handler. /// @@ -339,17 +355,17 @@ void PreProcessMessages() Log.Error($"Unknown table name: {tableName}"); continue; } - yield return (table, update); } } - (List, Dictionary>?) PreProcessInitialSubscription(InitialSubscription initSub) + (List, Dictionary>) PreProcessLegacySubscription(InitialSubscription initSub) { var dbOps = new List(); - // This is all of the inserts - Dictionary>? subscriptionInserts = null; + int cap = initSub.DatabaseUpdate.Tables.Sum(a => (int)a.NumRows); + // FIXME: shouldn't this be `new(initSub.DatabaseUpdate.Tables.Length)` ? + Dictionary> subscriptionInserts = new(capacity: cap); HashSet GetInsertHashSet(System.Type tableType, int tableSize) { @@ -358,49 +374,100 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) hashSet = new HashSet(capacity: tableSize, comparer: ByteArrayComparer.Instance); subscriptionInserts[tableType] = hashSet; } - return hashSet; } - int cap = initSub.DatabaseUpdate.Tables.Sum(a => (int)a.NumRows); - subscriptionInserts = new(capacity: cap); - // First apply all of the state foreach (var (table, update) in GetTables(initSub.DatabaseUpdate)) { var hashSet = GetInsertHashSet(table.ClientTableType, (int)update.NumRows); - foreach (var cqu in update.Updates) + PreProcessInsertOnlyTable(table, update, dbOps, hashSet); + } + return (dbOps, subscriptionInserts); + } + + /// + /// TODO: the dictionary is here for backwards compatibility and can be removed + /// once we get rid of legacy subscriptions. + /// + (List, Dictionary>) PreProcessSubscribeApplied(SubscribeApplied subscribeApplied) + { + var table = clientDB.GetTable(subscribeApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {subscribeApplied.Rows.TableName}"); + var dbOps = new List(); + HashSet inserts = new(); + + PreProcessInsertOnlyTable(table, subscribeApplied.Rows.TableRows, dbOps, inserts); + + var result = new Dictionary>(); + result[table.ClientTableType] = inserts; + + return (dbOps, result); + } + + void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, List dbOps, HashSet inserts) + { + foreach (var cqu in update.Updates) + { + var qu = DecompressDecodeQueryUpdate(cqu); + if (qu.Deletes.RowsData.Count > 0) { - var qu = DecompressDecodeQueryUpdate(cqu); - if (qu.Deletes.RowsData.Count > 0) + Log.Warn("Non-insert during an insert-only server message!"); + } + foreach (var bin in BsatnRowListIter(qu.Inserts)) + { + if (!inserts.Add(bin)) { - Log.Warn("Non-insert during a subscription update!"); + // Ignore duplicate inserts in the same subscription update. + continue; } - - foreach (var bin in BsatnRowListIter(qu.Inserts)) + var obj = table.DecodeValue(bin); + var op = new DbOp { - if (!hashSet.Add(bin)) - { - // Ignore duplicate inserts in the same subscription update. - continue; - } + table = table, + insert = new(obj, bin), + }; + dbOps.Add(op); + } + } - var obj = table.DecodeValue(bin); - var op = new DbOp - { - table = table, - insert = new(obj, bin), - }; + } - dbOps.Add(op); - } + + /// + /// TODO: the dictionary is here for backwards compatibility and can be removed + /// once we get rid of legacy subscriptions. + /// + List PreProcessUnsubscribeApplied(UnsubscribeApplied unsubApplied) + { + var table = clientDB.GetTable(unsubApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {unsubApplied.Rows.TableName}"); + var dbOps = new List(); + + // First apply all of the state + foreach (var cqu in unsubApplied.Rows.TableRows.Updates) + { + var qu = DecompressDecodeQueryUpdate(cqu); + if (qu.Inserts.RowsData.Count > 0) + { + Log.Warn("Non-insert during an UnsubscribeApplied!"); + } + foreach (var bin in BsatnRowListIter(qu.Deletes)) + { + var obj = table.DecodeValue(bin); + var op = new DbOp + { + table = table, + delete = new(obj, bin), + }; + dbOps.Add(op); } } - return (dbOps, subscriptionInserts); + return dbOps; } + + List PreProcessDatabaseUpdate(DatabaseUpdate updates) { var dbOps = new List(); @@ -485,10 +552,8 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) } } } - // Combine primary key updates and non-primary key updates dbOps.AddRange(primaryKeyChanges.Values); - return dbOps; } @@ -514,15 +579,21 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) ReducerEvent? reducerEvent = default; - // This is all of the inserts + // This is all of the inserts, used for updating the stale but un-cleared client cache. Dictionary>? subscriptionInserts = null; switch (message) { case ServerMessage.InitialSubscription(var initSub): - var (ops, subIns) = PreProcessInitialSubscription(initSub); - dbOps = ops; - subscriptionInserts = subIns; + (dbOps, subscriptionInserts) = PreProcessLegacySubscription(initSub); + break; + case ServerMessage.SubscribeApplied(var subscribeApplied): + (dbOps, subscriptionInserts) = PreProcessSubscribeApplied(subscribeApplied); + break; + case ServerMessage.SubscriptionError(var subscriptionError): + break; + case ServerMessage.UnsubscribeApplied(var unsubscribeApplied): + dbOps = PreProcessUnsubscribeApplied(unsubscribeApplied); break; case ServerMessage.TransactionUpdate(var transactionUpdate): // Convert the generic event arguments in to a domain specific event object @@ -560,11 +631,11 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) case ServerMessage.OneOffQueryResponse(var resp): PreProcessOneOffQuery(resp); break; + default: throw new InvalidOperationException(); } - // Logger.LogWarning($"Total Updates preprocessed: {totalUpdateCount}"); return new PreProcessedMessage { processed = new ProcessedMessage { message = message, dbOps = dbOps, timestamp = unprocessed.timestamp, reducerEvent = reducerEvent }, @@ -585,10 +656,10 @@ ProcessedMessage CalculateStateDiff(PreProcessedMessage preProcessedMessage) { if (!subscriptionInserts.TryGetValue(table.ClientTableType, out var hashSet)) { - // We still need to process tables that weren't included in subscription. - // Otherwise we won't delete no-longer-available values - hashSet = new HashSet(); - subscriptionInserts.Add(table.ClientTableType, hashSet); + // We don't know if the user is waiting for subscriptions on other tables. + // Leave the stale data for untouched tables in the cache; this is + // the best we can do. + continue; } foreach (var (rowBytes, oldValue) in table.IterEntries().Where(kv => !hashSet.Contains(kv.Key))) @@ -749,11 +820,11 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) stats.SubscriptionRequestTracker.FinishTrackingRequest(initialSubscription.RequestId); var eventContext = ToEventContext(new Event.SubscribeApplied()); OnMessageProcessCompleteUpdate(eventContext, dbOps); - if (subscriptions.TryGetValue(initialSubscription.RequestId, out var subscription)) + if (legacySubscriptions.TryGetValue(initialSubscription.RequestId, out var subscription)) { try { - subscription.OnApplied(eventContext); + subscription.OnApplied(eventContext, new SubscriptionAppliedType.LegacyActive(new())); } catch (Exception e) { @@ -762,6 +833,82 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } break; } + + case ServerMessage.SubscribeApplied(var subscribeApplied): + { + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.SubscribeApplied)}"); + stats.SubscriptionRequestTracker.FinishTrackingRequest(subscribeApplied.RequestId); + var eventContext = ToEventContext(new Event.SubscribeApplied()); + OnMessageProcessCompleteUpdate(eventContext, dbOps); + if (subscriptions.TryGetValue(subscribeApplied.QueryId.Id, out var subscription)) + { + try + { + subscription.OnApplied(eventContext, new SubscriptionAppliedType.Active(subscribeApplied.QueryId)); + } + catch (Exception e) + { + Log.Exception(e); + } + } + + break; + } + + case ServerMessage.SubscriptionError(var subscriptionError): + { + Log.Warn($"Subscription Error: ${subscriptionError.Error}"); + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.SubscriptionError)}"); + if (subscriptionError.RequestId.HasValue) + { + stats.SubscriptionRequestTracker.FinishTrackingRequest(subscriptionError.RequestId.Value); + } + // TODO: should I use a more specific exception type here? + var eventContext = ToEventContext(new Event.SubscribeError(new Exception(subscriptionError.Error))); + OnMessageProcessCompleteUpdate(eventContext, dbOps); + if (subscriptionError.QueryId.HasValue) + { + if (subscriptions.TryGetValue(subscriptionError.QueryId.Value, out var subscription)) + { + try + { + subscription.OnError(eventContext); + } + catch (Exception e) + { + Log.Exception(e); + } + } + } + else + { + Log.Warn("Received general subscription failure, disconnecting."); + Disconnect(); + } + + break; + } + + case ServerMessage.UnsubscribeApplied(var unsubscribeApplied): + { + stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.UnsubscribeApplied)}"); + stats.SubscriptionRequestTracker.FinishTrackingRequest(unsubscribeApplied.RequestId); + var eventContext = ToEventContext(new Event.UnsubscribeApplied()); + OnMessageProcessCompleteUpdate(eventContext, dbOps); + if (subscriptions.TryGetValue(unsubscribeApplied.QueryId.Id, out var subscription)) + { + try + { + subscription.OnEnded(eventContext); + } + catch (Exception e) + { + Log.Exception(e); + } + } + } + break; + case ServerMessage.TransactionUpdateLight(var update): { stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdateLight)}"); @@ -864,7 +1011,7 @@ public void InternalCallReducer(T args, CallReducerFlags flags) ))); } - void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) + void IDbConnection.LegacySubscribe(ISubscriptionHandle handle, string[] querySqls) { if (!webSocket.IsConnected) { @@ -873,7 +1020,7 @@ void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) } var id = stats.SubscriptionRequestTracker.StartTrackingRequest(); - subscriptions[id] = handle; + legacySubscriptions[id] = handle; webSocket.Send(new ClientMessage.Subscribe( new Subscribe { @@ -883,6 +1030,29 @@ void IDbConnection.Subscribe(ISubscriptionHandle handle, string[] querySqls) )); } + void IDbConnection.Subscribe(ISubscriptionHandle handle, string querySql) + { + if (!webSocket.IsConnected) + { + Log.Error("Cannot subscribe, not connected to server!"); + return; + } + + var id = stats.SubscriptionRequestTracker.StartTrackingRequest(); + // We use a distinct ID from the request ID as a sanity check that we're not + // casting request IDs to query IDs anywhere in the new code path. + var queryId = queryIdAllocator.Next(); + subscriptions[queryId] = handle; + webSocket.Send(new ClientMessage.SubscribeSingle( + new SubscribeSingle + { + RequestId = id, + Query = querySql, + QueryId = new QueryId(queryId), + } + )); + } + /// Usage: SpacetimeDBClientBase.instance.OneOffQuery("SELECT * FROM table WHERE sender = \"bob\""); [Obsolete("This is replaced by ctx.Db.TableName.RemoteQuery(\"WHERE ...\")", false)] public Task OneOffQuery(string query) where T : IDatabaseRow, new() => @@ -953,5 +1123,37 @@ public void FrameTick() OnMessageProcessComplete(preProcessedMessage); } } + + void IDbConnection.Unsubscribe(QueryId queryId) + { + if (!subscriptions.ContainsKey(queryId.Id)) + { + Log.Warn($"Unsubscribing from a subscription that the DbConnection does not know about, with QueryId {queryId.Id}"); + } + + var requestId = stats.SubscriptionRequestTracker.StartTrackingRequest(); + + webSocket.Send(new ClientMessage.Unsubscribe(new() + { + RequestId = requestId, + QueryId = queryId + })); + + } + } + + internal struct UintAllocator + { + private uint lastAllocated; + + /// + /// Allocate a new ID in a thread-unsafe way. + /// + /// A previously-unused ID. + public uint Next() + { + lastAllocated++; + return lastAllocated; + } } } diff --git a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt similarity index 94% rename from sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt rename to sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 2ab0a7db8cb..1287a5fdea4 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifyAllTablesParsed.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -3,7 +3,7 @@ Log: SpacetimeDBClient: Connecting to wss://spacetimedb.com example, OnConnect: { identity: Identity_1, - token: eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiI4ZjkwY2M5NGE5OTY4ZGY2ZDI5N2JhYTY2NTAzYTg5M2IxYzM0YjBiMDAyNjhhNTE0ODk4ZGQ5NTRiMGRhMjBiIiwiaWF0IjoxNzE4NDg3NjY4LCJleHAiOm51bGx9.PSn481bLRqtFwIh46nOXDY14X3GKbz8t4K4GmBmz50loU6xzeL7zDdCh1V2cmiQsoGq8Erxg0r_6b6Y5SqKoBA + token: eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiJjMjAwNDgzMTUyZDY0MmM3ZDQwMmRlMDZjYWNjMzZkY2IwYzJhMWYyYmJlYjhlN2Q1YTY3M2YyNDM1Y2NhOTc1Iiwic3ViIjoiNmQ0YjU0MzAtMDBjZi00YTk5LTkzMmMtYWQyZDA3YmFiODQxIiwiaXNzIjoibG9jYWxob3N0IiwiYXVkIjpbInNwYWNldGltZWRiIl0sImlhdCI6MTczNzY2NTc2OSwiZXhwIjpudWxsfQ.GaKhvswWYW6wpPpK70_-Tw8DKjKJ2qnidwwj1fTUf3mctcsm_UusPYSws_pSW3qGnMNnGjEXt7rRNvGvuWf9ow }, OnInsertUser: { eventContext: { @@ -420,25 +420,17 @@ Stats: { ReducerRequestTracker: { sampleCount: 3, - requestsAwaitingResponse: 6, - Min: sample#4, - Max: sample#2 + requestsAwaitingResponse: 6 }, OneOffRequestTracker: {}, SubscriptionRequestTracker: { - sampleCount: 1, - Min: sample#1, - Max: sample#1 + sampleCount: 1 }, AllReducersTracker: { - sampleCount: 9, - Min: reducer=send_message, - Max: reducer=set_name + sampleCount: 9 }, ParseMessageTracker: { - sampleCount: 10, - Min: type=TransactionUpdate,reducer=send_message, - Max: type=InitialSubscription + sampleCount: 10 } } } \ No newline at end of file diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt new file mode 100644 index 00000000000..ac76990117e --- /dev/null +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -0,0 +1,558 @@ +{ + Events: { + Log: SpacetimeDBClient: Connecting to wss://spacetimedb.com example, + OnConnect: { + identity: Identity_1, + token: eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiJjMjAwNDgzMTUyZDY0MmM3ZDQwMmRlMDZjYWNjMzZkY2IwYzJhMWYyYmJlYjhlN2Q1YTY3M2YyNDM1Y2NhOTc1Iiwic3ViIjoiNmQ0YjU0MzAtMDBjZi00YTk5LTkzMmMtYWQyZDA3YmFiODQxIiwiaXNzIjoibG9jYWxob3N0IiwiYXVkIjpbInNwYWNldGltZWRiIl0sImlhdCI6MTczNzY2NTc2OSwiZXhwIjpudWxsfQ.GaKhvswWYW6wpPpK70_-Tw8DKjKJ2qnidwwj1fTUf3mctcsm_UusPYSws_pSW3qGnMNnGjEXt7rRNvGvuWf9ow + }, + OnInsertUser: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.SubscribeApplied + }, + Db: {Scrubbed} + }, + user: { + identity: Identity_1, + online: true + } + }, + LogException: Unknown reducer unknown-reducer (Parameter 'Reducer'), + OnInsertUser: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_1, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.StdbIdentityConnected + } + } + }, + Db: {Scrubbed} + }, + user: { + identity: Identity_2, + online: true + } + }, + OnUpdateUser: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_2, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SetName, + name: A + } + } + }, + Db: {Scrubbed} + }, + oldUser: { + identity: Identity_1, + online: true + }, + newUser: { + identity: Identity_1, + name: A, + online: true + } + }, + OnSetName: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_2, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SetName, + name: A + } + } + }, + Db: {Scrubbed} + }, + OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_3, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Hello, A! + } + } + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_2, + sent: 1718487775346381, + text: Hello, A! + } + }, + OnSendMessage: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_3, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Hello, A! + } + } + }, + Db: {Scrubbed} + }, + OnUpdateUser: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_4, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SetName, + name: B + } + } + }, + Db: {Scrubbed} + }, + oldUser: { + identity: Identity_2, + online: true + }, + newUser: { + identity: Identity_2, + name: B, + online: true + } + }, + OnSetName: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_4, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SetName, + name: B + } + } + }, + Db: {Scrubbed} + }, + OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_5, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Hello, B! + } + } + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_1, + sent: 1718487783175083, + text: Hello, B! + } + }, + OnSendMessage: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_5, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Hello, B! + } + } + }, + Db: {Scrubbed} + }, + OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_6, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Goodbye! + } + } + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_2, + sent: 1718487787645364, + text: Goodbye! + } + }, + OnSendMessage: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_6, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Goodbye! + } + } + }, + Db: {Scrubbed} + }, + OnUpdateUser: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_7, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_2, + CallerAddress: Guid_1, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.StdbIdentityDisconnected + } + } + }, + Db: {Scrubbed} + }, + oldUser: { + identity: Identity_2, + name: B, + online: true + }, + newUser: { + identity: Identity_2, + name: B, + online: false + } + }, + OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_8, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Goodbye! + } + } + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_1, + sent: 1718487794937841, + text: Goodbye! + } + }, + OnSendMessage: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.Reducer, + ReducerEvent: { + Timestamp: DateTimeOffset_8, + Status: { + $type: Status.Committed + }, + CallerIdentity: Identity_1, + CallerAddress: Guid_2, + EnergyConsumed: {}, + Reducer: { + $type: Reducer.SendMessage, + text: Goodbye! + } + } + }, + Db: {Scrubbed} + }, + OnDeleteMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.UnsubscribeApplied + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_2, + sent: 1718487775346381, + text: Hello, A! + } + }, + OnDeleteMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.UnsubscribeApplied + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_1, + sent: 1718487783175083, + text: Hello, B! + } + }, + OnDeleteMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.UnsubscribeApplied + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_2, + sent: 1718487787645364, + text: Goodbye! + } + }, + OnDeleteMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.UnsubscribeApplied + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_1, + sent: 1718487794937841, + text: Goodbye! + } + }, + LogWarning: Subscription Error: $bad query dude, + OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.SubscribeApplied + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_2, + sent: 1718487775346381, + text: Hello, A! + } + }, + OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.SubscribeApplied + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_1, + sent: 1718487783175083, + text: Hello, B! + } + }, + OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.SubscribeApplied + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_2, + sent: 1718487787645364, + text: Goodbye! + } + }, + OnInsertMessage: { + eventContext: { + Reducers: {Scrubbed}, + SetReducerFlags: {}, + Event: { + $type: Event.SubscribeApplied + }, + Db: {Scrubbed} + }, + message: { + sender: Identity_1, + sent: 1718487794937841, + text: Goodbye! + } + } + }, + FinalSnapshot: { + User: [ + { + identity: Identity_1, + name: A, + online: true + }, + { + identity: Identity_2, + name: B, + online: false + } + ], + Message: [ + { + sender: Identity_1, + sent: 1718487794937841, + text: Goodbye! + }, + { + sender: Identity_2, + sent: 1718487787645364, + text: Goodbye! + }, + { + sender: Identity_1, + sent: 1718487783175083, + text: Hello, B! + }, + { + sender: Identity_2, + sent: 1718487775346381, + text: Hello, A! + } + ] + }, + Stats: { + ReducerRequestTracker: { + sampleCount: 3, + requestsAwaitingResponse: 6 + }, + OneOffRequestTracker: {}, + SubscriptionRequestTracker: { + sampleCount: 1, + requestsAwaitingResponse: 2 + }, + AllReducersTracker: { + sampleCount: 9 + }, + ParseMessageTracker: { + sampleCount: 14 + } + } +} \ No newline at end of file diff --git a/sdks/csharp/tests~/SnapshotTests.cs b/sdks/csharp/tests~/SnapshotTests.cs index 6b0bc77bf44..df57fde3042 100644 --- a/sdks/csharp/tests~/SnapshotTests.cs +++ b/sdks/csharp/tests~/SnapshotTests.cs @@ -104,7 +104,7 @@ private static ServerMessage.IdentityToken SampleId(string identity, string toke Address = Address.From(Convert.FromBase64String(address)) ?? throw new InvalidDataException("address") }); - private static ServerMessage.InitialSubscription SampleSubscriptionUpdate( + private static ServerMessage.InitialSubscription SampleLegacyInitialSubscription( uint requestId, ulong hostExecutionDuration, List updates @@ -118,6 +118,61 @@ List updates } }); + private static ServerMessage.SubscribeApplied SampleSubscribeApplied( + uint requestId, + uint queryId, + ulong hostExecutionDuration, + TableUpdate tableUpdate + ) => new(new() + { + RequestId = requestId, + TotalHostExecutionDurationMicros = hostExecutionDuration, + QueryId = new(queryId), + Rows = new() + { + // This message contains redundant data, shrug. + // Copy out the redundant fields. + TableId = tableUpdate.TableId, + TableName = tableUpdate.TableName, + TableRows = tableUpdate + } + }); + + private static ServerMessage.UnsubscribeApplied SampleUnsubscribeApplied( + uint requestId, + uint queryId, + ulong hostExecutionDuration, + TableUpdate tableUpdate + ) => new(new() + { + RequestId = requestId, + TotalHostExecutionDurationMicros = hostExecutionDuration, + QueryId = new(queryId), + Rows = new() + { + // This message contains redundant data, shrug. + // Copy out the redundant fields. + TableId = tableUpdate.TableId, + TableName = tableUpdate.TableName, + TableRows = tableUpdate + } + }); + + private static ServerMessage.SubscriptionError SampleSubscriptionError( + uint? requestId, + uint? queryId, + uint? tableId, + string error, + ulong hostExecutionDuration + ) => new(new() + { + RequestId = requestId, + QueryId = queryId, + TableId = tableId, + Error = error, + TotalHostExecutionDurationMicros = hostExecutionDuration, + }); + private static ServerMessage.TransactionUpdate SampleTransactionUpdate( ulong timestamp, string callerIdentity, @@ -189,8 +244,14 @@ private static byte[] Encode(in T value) where T : IStructuralReadWrite return o.ToArray(); } + private static readonly uint USER_TABLE_ID = 4097; + private static readonly string USER_TABLE_NAME = "user"; + private static readonly uint MESSAGE_TABLE_ID = 4098; + private static readonly string MESSAGE_TABLE_NAME = "message"; + + private static TableUpdate SampleUserInsert(string identity, string? name, bool online) => - SampleUpdate(4097, "user", [new User + SampleUpdate(USER_TABLE_ID, USER_TABLE_NAME, [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = name, @@ -198,7 +259,7 @@ private static TableUpdate SampleUserInsert(string identity, string? name, bool }], []); private static TableUpdate SampleUserUpdate(string identity, string? oldName, string? newName, bool oldOnline, bool newOnline) => - SampleUpdate(4097, "user", [new User + SampleUpdate(USER_TABLE_ID, USER_TABLE_NAME, [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = newName, @@ -210,70 +271,169 @@ private static TableUpdate SampleUserUpdate(string identity, string? oldName, st Online = oldOnline }]); - private static TableUpdate SampleMessage(string identity, ulong sent, string text) => - SampleUpdate(4098, "message", [new Message - { - Sender = Identity.From(Convert.FromBase64String(identity)), - Sent = sent, - Text = text - }], []); - private static ServerMessage[] SampleDump() => [ - SampleId( - "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiI4ZjkwY2M5NGE5OTY4ZGY2ZDI5N2JhYTY2NTAzYTg5M2IxYzM0YjBiMDAyNjhhNTE0ODk4ZGQ5NTRiMGRhMjBiIiwiaWF0IjoxNzE4NDg3NjY4LCJleHAiOm51bGx9.PSn481bLRqtFwIh46nOXDY14X3GKbz8t4K4GmBmz50loU6xzeL7zDdCh1V2cmiQsoGq8Erxg0r_6b6Y5SqKoBA", - "Vd4dFzcEzhLHJ6uNL8VXFg==" - ), - SampleSubscriptionUpdate( - 1, 366, [SampleUserInsert("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true)] - ), - SampleTransactionUpdate(0, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "unknown-reducer", 0, 40, [], null - ), - SampleTransactionUpdate( - 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "__identity_connected__", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], - null - ), - SampleTransactionUpdate( - 1718487768057579, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", - 1, "set_name", 4345615, 70, [SampleUserUpdate("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, "A", true, true)], - Encode(new Reducer.SetName { Name = "A" }) - ), - SampleTransactionUpdate( - 1718487775346381, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 1, "send_message", 2779615, 57, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487775346381, "Hello, A!")], - Encode(new Reducer.SendMessage { Text = "Hello, A!" }) - ), - SampleTransactionUpdate( - 1718487777307855, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 2, "set_name", 4268615, 98, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, "B", true, true)], - Encode(new Reducer.SetName { Name = "B" }) - ), - SampleTransactionUpdate( - 1718487783175083, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", - 2, "send_message", 2677615, 40, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487783175083, "Hello, B!")], - Encode(new Reducer.SendMessage { Text = "Hello, B!" }) - ), - SampleTransactionUpdate( - 1718487787645364, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 3, "send_message", 2636615, 28, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487787645364, "Goodbye!")], - Encode(new Reducer.SendMessage { Text = "Goodbye!" }) - ), - SampleTransactionUpdate( - 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "__identity_disconnected__", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], - null - ), - SampleTransactionUpdate( - 1718487794937841, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", - 3, "send_message", 2636615, 34, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487794937841, "Goodbye!")], - Encode(new Reducer.SendMessage { Text = "Goodbye!" }) - ), - ]; - - [Fact] - public async Task VerifyAllTablesParsed() + private static Message SampleMessage(string identity, ulong sent, string text) => new() + { + Sender = Identity.From(Convert.FromBase64String(identity)), + Sent = sent, + Text = text + }; + + private static TableUpdate SampleMessageInsert(List messages) => + SampleUpdate(MESSAGE_TABLE_ID, MESSAGE_TABLE_NAME, messages, []); + + private static TableUpdate SampleMessageDelete(List messages) => + SampleUpdate(MESSAGE_TABLE_ID, MESSAGE_TABLE_NAME, [], messages); + + public static IEnumerable SampleDump() + { + var sampleMessage0 = SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487775346381, "Hello, A!"); + var sampleMessage1 = SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487783175083, "Hello, B!"); + var sampleMessage2 = SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487787645364, "Goodbye!"); + var sampleMessage3 = SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487794937841, "Goodbye!"); + + yield return new object[] { "LegacySubscribeAll", + new ServerMessage[] { + SampleId( + "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", + "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiJjMjAwNDgzMTUyZDY0MmM3ZDQwMmRlMDZjYWNjMzZkY2IwYzJhMWYyYmJlYjhlN2Q1YTY3M2YyNDM1Y2NhOTc1Iiwic3ViIjoiNmQ0YjU0MzAtMDBjZi00YTk5LTkzMmMtYWQyZDA3YmFiODQxIiwiaXNzIjoibG9jYWxob3N0IiwiYXVkIjpbInNwYWNldGltZWRiIl0sImlhdCI6MTczNzY2NTc2OSwiZXhwIjpudWxsfQ.GaKhvswWYW6wpPpK70_-Tw8DKjKJ2qnidwwj1fTUf3mctcsm_UusPYSws_pSW3qGnMNnGjEXt7rRNvGvuWf9ow", + "Vd4dFzcEzhLHJ6uNL8VXFg==" + ), + SampleLegacyInitialSubscription( + 1, 366, [SampleUserInsert("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true)] + ), + SampleTransactionUpdate(0, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "unknown-reducer", 0, 40, [], null + ), + SampleTransactionUpdate( + 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "__identity_connected__", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], + null + ), + SampleTransactionUpdate( + 1718487768057579, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 1, "set_name", 4345615, 70, [SampleUserUpdate("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, "A", true, true)], + Encode(new Reducer.SetName { Name = "A" }) + ), + SampleTransactionUpdate( + 1718487775346381, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 1, "send_message", 2779615, 57, [SampleMessageInsert([ + sampleMessage0 + ])], + Encode(new Reducer.SendMessage { Text = "Hello, A!" }) + ), + SampleTransactionUpdate( + 1718487777307855, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 2, "set_name", 4268615, 98, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, "B", true, true)], + Encode(new Reducer.SetName { Name = "B" }) + ), + SampleTransactionUpdate( + 1718487783175083, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 2, "send_message", 2677615, 40, [SampleMessageInsert([ + sampleMessage1 + ])], + Encode(new Reducer.SendMessage { Text = "Hello, B!" }) + ), + SampleTransactionUpdate( + 1718487787645364, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 3, "send_message", 2636615, 28, [SampleMessageInsert([ + sampleMessage2 + ])], + Encode(new Reducer.SendMessage { Text = "Goodbye!" }) + ), + SampleTransactionUpdate( + 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "__identity_disconnected__", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], + null + ), + SampleTransactionUpdate( + 1718487794937841, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 3, "send_message", 2636615, 34, [SampleMessageInsert([ + sampleMessage3 + ])], + Encode(new Reducer.SendMessage { Text = "Goodbye!" }) + ), + } + }; + yield return new object[] { "SubscribeApplied", + new ServerMessage[] { + SampleId( + "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", + "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiJjMjAwNDgzMTUyZDY0MmM3ZDQwMmRlMDZjYWNjMzZkY2IwYzJhMWYyYmJlYjhlN2Q1YTY3M2YyNDM1Y2NhOTc1Iiwic3ViIjoiNmQ0YjU0MzAtMDBjZi00YTk5LTkzMmMtYWQyZDA3YmFiODQxIiwiaXNzIjoibG9jYWxob3N0IiwiYXVkIjpbInNwYWNldGltZWRiIl0sImlhdCI6MTczNzY2NTc2OSwiZXhwIjpudWxsfQ.GaKhvswWYW6wpPpK70_-Tw8DKjKJ2qnidwwj1fTUf3mctcsm_UusPYSws_pSW3qGnMNnGjEXt7rRNvGvuWf9ow", + "Vd4dFzcEzhLHJ6uNL8VXFg==" + ), + SampleSubscribeApplied( + 1, 1, 366, SampleUserInsert("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true) + ), + SampleSubscribeApplied( + 1, 2, 277, SampleUpdate(MESSAGE_TABLE_ID, MESSAGE_TABLE_NAME, [], []) + ), + SampleTransactionUpdate(0, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "unknown-reducer", 0, 40, [], null + ), + SampleTransactionUpdate( + 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "__identity_connected__", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], + null + ), + SampleTransactionUpdate( + 1718487768057579, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 1, "set_name", 4345615, 70, [SampleUserUpdate("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, "A", true, true)], + Encode(new Reducer.SetName { Name = "A" }) + ), + SampleTransactionUpdate( + 1718487775346381, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 1, "send_message", 2779615, 57, [SampleMessageInsert([ + sampleMessage0 + ])], + Encode(new Reducer.SendMessage { Text = "Hello, A!" }) + ), + SampleTransactionUpdate( + 1718487777307855, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 2, "set_name", 4268615, 98, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, "B", true, true)], + Encode(new Reducer.SetName { Name = "B" }) + ), + SampleTransactionUpdate( + 1718487783175083, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 2, "send_message", 2677615, 40, [SampleMessageInsert([ + sampleMessage1 + ])], + Encode(new Reducer.SendMessage { Text = "Hello, B!" }) + ), + SampleTransactionUpdate( + 1718487787645364, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 3, "send_message", 2636615, 28, [SampleMessageInsert([ + sampleMessage2 + ])], + Encode(new Reducer.SendMessage { Text = "Goodbye!" }) + ), + SampleTransactionUpdate( + 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", + 0, "__identity_disconnected__", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], + null + ), + SampleTransactionUpdate( + 1718487794937841, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", + 3, "send_message", 2636615, 34, [SampleMessageInsert([ + sampleMessage3 + ])], + Encode(new Reducer.SendMessage { Text = "Goodbye!" }) + ), + // Let's pretend the user unsubscribed from the table Messages... + SampleUnsubscribeApplied(0, + 2, 55, SampleMessageDelete([sampleMessage0, sampleMessage1, sampleMessage2, sampleMessage3])), + // Tried to resubscribe unsuccessfully... + SampleSubscriptionError(0, 3, MESSAGE_TABLE_ID, "bad query dude", 69), + // Then successfully resubscribed. + SampleSubscribeApplied(0, 4, 53, SampleMessageInsert([sampleMessage0, sampleMessage1, sampleMessage2, sampleMessage3])) + } + }; + + } + + [Theory] + [MemberData(nameof(SampleDump))] + public async Task VerifySampleDump(string dumpName, ServerMessage[] sampleDumpParsed) { var events = new Events(); @@ -288,8 +448,6 @@ public async Task VerifyAllTablesParsed() .OnConnect((conn, identity, token) => events.Add("OnConnect", new { identity, token })) .Build(); - var sampleDumpParsed = SampleDump(); - // But for proper testing we need to convert it back to raw binary messages as if it was received over network. var sampleDumpBinary = sampleDumpParsed.Select( (message, i) => @@ -300,6 +458,9 @@ public async Task VerifyAllTablesParsed() case ServerMessage.InitialSubscription(var _): client.stats.SubscriptionRequestTracker.StartTrackingRequest($"sample#{i}"); break; + case ServerMessage.SubscribeApplied(var _): + client.stats.SubscriptionRequestTracker.StartTrackingRequest($"sample#{i}"); + break; case ServerMessage.TransactionUpdate(var _): client.stats.ReducerRequestTracker.StartTrackingRequest($"sample#{i}"); break; @@ -368,6 +529,7 @@ await Verify( Stats = client.stats } ) + .UseParameters(dumpName) .AddExtraSettings(settings => settings.Converters.AddRange([ new EventsConverter(), new TimestampConverter(), diff --git a/sdks/csharp/tests~/VerifyInit.cs b/sdks/csharp/tests~/VerifyInit.cs index 9d8249d959e..eab677634bd 100644 --- a/sdks/csharp/tests~/VerifyInit.cs +++ b/sdks/csharp/tests~/VerifyInit.cs @@ -55,14 +55,7 @@ public override void Write(VerifyJsonWriter writer, NetworkRequestTracker value) ); } - if ( - value.GetMinMaxTimes(int.MaxValue) is - { Min.Metadata: var Min, Max.Metadata: var Max } - ) - { - writer.WriteMember(value, Min, nameof(Min)); - writer.WriteMember(value, Max, nameof(Max)); - } + // We don't use the stats, since they are nondeterministic. writer.WriteEndObject(); } diff --git a/sdks/csharp/unity-tests~ b/sdks/csharp/unity-tests~ index e9e044980da..a8d9e359875 160000 --- a/sdks/csharp/unity-tests~ +++ b/sdks/csharp/unity-tests~ @@ -1 +1 @@ -Subproject commit e9e044980da900a2f63799bb5b93cb3f91da4b01 +Subproject commit a8d9e359875ad22b409fda8be204e53d2d7b96e7 From 27be3019bba451e6c93594df09d633b1a611fed5 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Fri, 24 Jan 2025 13:27:04 -0800 Subject: [PATCH 164/223] Bump version to `1.0.0-rc3-hotfix3` (#222) ## Description of Changes Bump the version and include the DLLs from the corresponding NuGet packages / SpacetimeDB version. ## API - [ ] This is an API breaking change to the SDK I believe not? ## Requires SpacetimeDB PRs I believe this requires tag `v1.0.0-rc3-hotfix3` ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: v1.0.0-rc3-hotfix3 ## Testing Only automated testing, since this itself is just a version bump. --------- Co-authored-by: Zeke Foppa --- sdks/csharp/.github/workflows/test.yml | 4 ++-- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- ...{1.0.0-rc3.meta => 1.0.0-rc3-hotfix3.meta} | 0 .../analyzers.meta | 0 .../analyzers/dotnet.meta | 0 .../analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/lib.meta | 0 .../lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 66560 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 66048 -> 0 bytes 13 files changed, 4 insertions(+), 4 deletions(-) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3.meta => 1.0.0-rc3-hotfix3.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (91%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/lib/netstandard2.1.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc3-hotfix3}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll diff --git a/sdks/csharp/.github/workflows/test.yml b/sdks/csharp/.github/workflows/test.yml index 84d3c552bdd..460ab97789a 100644 --- a/sdks/csharp/.github/workflows/test.yml +++ b/sdks/csharp/.github/workflows/test.yml @@ -89,8 +89,8 @@ jobs: - name: Install SpacetimeDB CLI from the local checkout run: | - cargo install --path SpacetimeDB~/crates/cli --locked --message-format=short - cargo install --path SpacetimeDB~/crates/standalone --locked --message-format=short + cargo install --force --path SpacetimeDB~/crates/cli --locked --message-format=short + cargo install --force --path SpacetimeDB~/crates/standalone --locked --message-format=short # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). rm $HOME/.cargo/bin/spacetime || echo "haven't run on this host before" ln -s $HOME/.cargo/bin/spacetimedb-cli $HOME/.cargo/bin/spacetime diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 081cb2dee3d..4c0eca01535 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -17,14 +17,14 @@ README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk 1.0.0 - 1.0.0-rc3 + 1.0.0-rc3-hotfix3 $(DefaultItemExcludes);*~/** packages - + diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll similarity index 91% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 399de6b034e49f96a3d6a61eba8ff60d2d33334a..f651b04369b3e1e2e782ade23cff5443c37d9908 100755 GIT binary patch delta 1839 zcmXw)eQZ-@6voecZ_C)$@v(MvyS+Dby)ZJz#zwofr3Slnf-`Cf5zRtOT5ebNLC0YH z0a4jq28nzmIA8cj$mlYLpfMvhizc9!bc^6e2mvwj5js1gCMKHb5{N-P@5yM=r_cSJ z=RNPaZ?|6anrvQ^-+jk&BEI$U$Z?g8j$C|wN&91fD2NvWn{}kxZgZo-OZ5@JtGrrT z%RAT_c8(9RHImKBKV+}5w>gvS*1yMa4IjJb&uozbE$sKqk-(>GS%J59Zni(EYJgr? zqBOt&)GJ<4AjMC2ww7tG!|1m;IFa8vwWc=L1d)s&%2jw19+u}8w1oUH^txs!bBk8_ zlR8WB?MbaHrRYp_)7db*#}6lK*#$m{)f@a4`k(oeq&|4THO`JRP_AU%VeNn##Z8ir?8SrUCL5{FUEE{S~|s8L5XWpvDJRdvdEsoE+y zKfBW!IiN-)(LX}fcC4n9_=1Z52ChA!8dM!1ZsP7y#}IWM#_9zBWv5m(p^j4~OZ+Nn zPRz!&F6ZC@wLn!S)6BByAj@J-S;q5m$+DQ=jXb4PQ$|OAS=EWR5{V$eX^FJSr!n6y zdtg9`FDOk*oek=2VE(3Rh&<19X=OLnVOl#bI`aoz&ef099Fgmok2axr0ye1g15 z{t)?T(mB+uW+@lyE*Go9q_J`_LyWvh-XxzU%@WCy&y&xS2RnA)r}~`i8~$-$Eq?Jo z^sO6ADQ1P}oF+Y2A^v%?6?Bh8^5pa6VTDM#SBR>c{HhfqA0{6o9wVP1Zjw)vo+C0x z>UN4hlvPd+M_*7@IX!SkYr~64rH#Bvvyd~Zr!h^oif2s~gtP%NejTkpfK1OO1G0CTe&z#sZ^5U}p4m=-P`{nITpH(e7 zHhbfXx=iDh&#N{*$6!NKLt{f@{a(Xc-?e*RvU|U`t~uE3O$3A9mSpD+Bj7W9K_h9b zZw>@olJO>^$(Km_5^X%y)%5t{f%XpEKe%{mw3nhvuqiEd|$^0iT1!L%kM*o`}5v-J#@it*au1IhW+4$ zI%tL!usG+{M?S3={ceh6eP=UZ6u SpFmH&bTG60r$5+8W6}TDzzCuM delta 1844 zcmXw)eP|PR7{{OAU1Dord}-3g{+eTHW0kJ1Ce2&3j*^g$O__@_-4MsfOE0!Yoi9wr z#^}{3n@;A!Ph~^JNG+nH$d*5*u#J?o%ue0@D0{ON;}Rx=l?g*O!NH#2L%rj^{od#K z{+@g8lID!-s&QTY_ybd4-{gtxF*`ezz4Y3W@FRdI$c@2cQ?}Jo=U`BWr`CS~Hj7qe zjo8Xovom6ZtyUhJ#AWs>drL6IV*c|yt`VQl2J#z~9zUz(kMw-GhRuqw{(|LUa~Gsx z5$}Ti(9S);K^Ld>aD8LTVf0(9g2*4b=6FK!>Z2X3o833aqau|BvtnlH}L9F>j-tuVD+rHzg=rSYagXdf%pVz zQO+i`LEG?Ndzq?CrI}UPK~?3Ps*2C2MOEee4&*v-rHm7K-tHtGCK5q{(-P@dPh)@LZMbKT2At zlFzC@zDQbS&OwLZq<3qy;V? z^sP6i@Rr1$UVP9$>^a$qBd(J9&?-4@h+q3VzVtM}Am(L&g zD0%Jo!E1TfS6?^#0}Q&|U9K+IGy9UBPM1HC^mV5KiFn-Q^Siy?RB|8?Oa;9`Pa+lc zxf2OrPu$xR%y<6uP<3CQk4^&Huu;L^`!Dbq#NYhE+h`UxhJP)1tj2@mi-LUV!=S3lLlP-`H^Qn|It}mHW5imxplqlPx2?Biq`9 zZ<2kpXR@wpv1G2VK4*Fo0LY20bLSX{M{`a#m)GvtRP`u$M4;r^)Cn%|LjscEgKkJc z0DT;H7oPjU4PM++SRKGh5M2<@gW$oG^gc`^aQ8tEuJNJ<^EXOCFq z755;Z(pr~lTcv8FAXQOuw^D0E!L4;)D{blje(v*TX267>zkYnz^?ld%kIwx*_wzjG zIp=xKd6$`a-(lSJ>y)FE^5FHK|0wksw(=Jto*1Gqr?=jft{zQ(sm)`0>`QGX&tFhc zu(Z5vUis|B1*Nl>EGb)FaKYSy@)b)87Az?kHhxmU;<7n&yQQV2w0A>K7_QVdH zGB%^U>WjrnP1~u|u`TKHlc1Few^J&maHidw+^Yv5Sce?v_9}$*6b^Lt&hb>{GQo;9 z=_zao7H@WShxjAw^|$>0ETE;{N#Y>(>8 zkt&s2f3&3}_s-Fb4mPcILUSv6A@eY1ze~6eq?|RU3Le!JXlU1pR@sPw<3!MehalgS zkUE-EfYoCc0Bn*2b|N`91kFV$zSd`y`YHy%wPAIPfGn${V}^3Vqs4G{xF6!%vXu3Q zSkU>Lb9PL3wNglGrxnh0Cos*}8MMuF3il=iuyrj%k10jD2_fuUP>&MH!odQUg@ZNE zeWhV5YAhVdL)HzBaacF`D37cg*~+@Xf^Aqg=ly8ih?5h>QgYXgt-Ti%by8D z!nzUcJ;+o__YN^U3#zW2j#15(AR$vJgLR1Xau<=rXjt<4ii zNKMKH#g~uO%2280@{yqw$?_2)%;vIu;sI(S; za&(cAI7Ij8a*V$mJ(~2lM~@%PrwqW(r%3Araw~9LObO#i@RR0qHU{7Le9DTB&F6e6 zOT*zn^7!%LK*k&p=}PuH^LN zeOI!G@4GS-&b0_(HjnSS@zNZ-@5T$!uad0)Ahw!%4gt#$^*$ zqx30#r%IgMFv4|7@rCr!Y+S>br0{xFwri5FVl>(phRo6IskprIqroxla(-&N5hh%T zh~YC4F1$u&P2ymOllMKriZM{*Du8_>V~nXw*;wd&g}qFrj5iFoE)8dY8Cz_3zg&Wi zaF4R$%E^|~yd=W879mW(oWhw2o(@CXIhA(_-J~$Mlnie~%yk85g?iRRCdUfL zWO9{sjv-3RaC*WJuS*=_COgD&NXWXDodr>bD1C52gJoQaHk_!MQLcJW1eY4u%R7-U1Sy zEIypqh&uKf{!3Y;IQjkP8vY#UPH+v6VurO832Yx{1m!0x_1!CM%y zaOqR%Wx^Sls_^-uZ8YyB-9+9v<(??-o8*w1;*__DwRcRo1gaWz+@cI8u#}FuEXoBC zWeFz~r4%X_UA>e!c~r^H!c~RqEt_j-??Ui=b8oGOirQW z3IA56QI37M5K`Dnf;lN&(v9zW$9KJW_;RPE_{=p6dVP}X9ybc$hrJ}&I+)_f!73xk ze|?&-b?fQL(^CAoI7TJG`|rL&ANRsr5WWhBI*;sOvJKxV9iC~{4gqn(-^A=^T8-=V zt$4|9EK9wrw;MpVT<;QKXgmPzXIhP^q!$Co)qNkh;dFkggt*46#nBtx&PVC2W$iF3 zZZPP^`dAlJDGkF5;AmY;rI^E;;E26A9NUXu%e%T0NQa#APFOLfVmAi7otoV8p3tnp zdnQj@Td~6K^5KhQ_E1YXhDNZ}at!SNCEj@@gb*9}%IMWhs8#WHMCGgOk}`j&(H$|`_?_nIXY`I5?7 zKz`SU)3B9r0@HHl$7;>%Ag54~eX4VJE4M&B2R6}%+r^tQod2PVSRc9V<9&p?Sy`@? zu#ouoitJ!Kpc@_`!pkw-u7&&rp?s<=39936Wh>wiz8FyPGr%fScxl||lwBg$m4F=# zyb2P|GM=yqwu4GYWvfMhtFxvG+YViGJFdYAIpwHtEwCagx~N#nLUKOi8pD#5k79#P z**X}yX0N#v8_W^vjzdq2vTD#mxpt6llcbHKx}puHGU#~NbF-tmY(3m8D~gBkxG^r1 z7-%DFI^S)3d_NoD6aIrNr*7daj4mqUKqF~WgfoEav3CCpg%9H>i+TEqfDvk?v_8t-v^{%E{nFKlJYSlHI_uqUaPmUXR=Q&290 zT47oGDjw$EZfBLwoVUh(_q)EhAib_NP(o%jkS4}EG8VT0akJeT;Ye+;0>j^< zb!vlrM_^!n=!4=RcFqHjV+Rk(}V)T^#0vK*3!*yf+_?ULLSVyeAAD(Uk*heJ+YGMgk zyPJU22+a^P5A(3*0kmC}f6Qi0`8J#^<7dL~gYc<%2oM!-u4yUuF~?Vwrd#}41U`nJ zOWR{chojkY(6EP>3LJRdoE$l(xW|@?i=1~R*HphpeS(7Mle>5u{K{^~0VIOW}A;hgeQ zSCr~Ssj_G;f(4TAN!3)hI0S1w%fjT&}qpZjj=VJr;8#L9jJ(Y~8v z(rggBp1m7ytK{Mp`hiTC6JHQpw2I$*B2m z^^C+~k4!AKSXgWdQlH~%Jw8^Dpv}d#YHH3mM7>bN)38Ks_a>4yW}RXz%_x%@&>&{orB(x zE_*}N8Te4@_n1?D=o09X9n#_736;-Y0$qF+zs0~-`FYNpg}!i72s$aA6|$USJ?OGx zcz4P5tdPvvLnriL%FY&bdQ!zx67jb(wl2;56}yD(C3E9*^uFZqTTsgJ!mG|iUvf-~ zy^WNeFn*ko3$plr-XXVK)=g7p`{q(E_QE*bb-`C_SjSId5Im+isss9Jg}y2tMAQ_Y zQ-y0fkFSz=)c25d6-5=waEz8u%kW7J(!wzo@o>0u<2`+Byw(!$VK*Kw2N92W)c31c zJRBEnyqU3hSiWw&XOE3nAn_h?XF!hMlKWBcO5*bZ~tzKC`7Q})F)j2YE>0i7Rz+^dL%#)_Vg;c{QZ_0o@zdy8Q` zZeLs``MLYzONj0s_a4KrOr@k#_BcelFEVE~_|d-jiVQ3_9B<~>#=FqCVPC9}u4G?) z4bC|3Npu#qu%kQj$qk>-#p`@lVx7-xs56De>Wr(k#?LSRL!F;#qPSPZ;$etCLjs8( z&#nG(Iiro26Ndr&p`54eiC8(A8XGiK&UiC^@a8GQo)#qM4w z22`^IA#r$IH_eMuweG zPv*u3C$6V7b1K<5v7XmUR|(5g9I6CZPZ_JN=lM{@>Nz2?o?>A=DKuKo-Ld>nPCfU> z;-Q{5VvLFPycPVodfq8X{6q6EbEf&_ALSwaV7c0m~ zU)P;up;7B+Fyf|b{Rdc&tMxu9KvT7rbP{UKoY~;SwU%a1B^xK!`X%Wqq1NJ1CBRzC z$m6x14Rx&6lM`z#7S@_VW3}!VE67Q&_35$DsP(HDanrSa3)bUmeLxD(RIMeQgjzFa zHaKyurI}O7#)-9lSGr25wK!A>u+}p2c&#shI#z4EmyBNri-onO&{(a<#0qlKYdt9z z8nv#+h?}nU`>-BY>yM=XP1Rb`NvJh*W`h&gTADePY@Ar@ze`sMwHAje0oGbZ9&9jo=ZiM19BYfYiCTK^(ekdt2PM`EE->y{XC)3t5`>v6}B4pM-o zjvu+}p2c&+C_9ji4y;E10a#ll)sXsp(| zV+A?swcZyCjaqlXh?}l8K1e>k)_tS^P1Rb`NvJh*W`h&gTADePY@Ar@zS31ft;L~A zfVGy9$7?+w>R7Gu!AHE-VqvW*G*;_B#R_uLYyEyKG-^E%BW}9ZXTW;gx-OOiG*xR! zC!yBNnGH@{YiZ_GvTi-onO&{(a%j}_#k z*IIiT-jbr$qcP&9Ykd~1$JP35DL_-TmUI$o&79fb#I=@YP9+;B)_SsZl~8MOs1jhU zW#sW%;~R%~t?_|Lyw+l2ttm8C>#SHoPI|3RiG@b3r(wiR*ZO=|kE``;DL_-TmUI$o z&79fb#I=@YP9+;B*1A->N~pCsR0*)wGV*w>@v(5c*7(dMUTd+i))X46b@y07PI|2e z#6qLi^DyG3YrP28<7&NB3eZ%oC7py?GiNq9ajm79Q_04OwJw*g5^60DRRXNFj67cJ zMNr3%A^6NBUTd+i))X46^_W;ePI|2;#X_Uj7h}Xt*SZqc<7&ND3eZ%oC7py?GiNq9 zajm79Q_04OwO%J(CDd9RssvbT8F{?ci=mFy8lRcOYb_SmnnGi>E{zrBq}O_3EHr9; z8AjZ6tvAAYT&=H>0yI@?NhhJ!%$W^NTx)6ORI+hmt*?`=5^60DRRXNFjNH~*>X&Pj zYJ<;_*DjG*;XQc!nVK}bnc@?De0rfLw02os zD>sm&^j{>}a%yit7QAyOrT-MsVq_S8k;J{5z7f$bk82;MwotSy;@UcDn~C<~xOP9a zN0HRppT)KBQTvf-FNteEr54``s8Rm0XsDAg8g#Is@?cE+q`!DdD2!DhIhU^%kv|0Rm&kw=qFR(3EO7Th{e zRxOqNh;;h!e z*08h=rIs}pi_KKt#AOu(3t%Y-1jK4gwo3TiN#h_E|9a@2HV2Y zHk4jALM&gg268!<)h^f$mUf|xvU9}pH7#=Sk<~uf9+vi@%(6LR!Dm>go17}MIs`kw z(jgQq!}spK{@>Cf2llLv!H%$W428-r70Y+Dl!&EMu+sp%O;o{7p{%m&8v@$HMULF5 zoMQKBU)X~h6tt)9KIQ|z7}OgYAs zYFlyl52hYt3Rn}50l~mArZj8ffgqT6j49okct8lIA7jd}CLS1q8ONA1t%(PSVCFHV zpf&M85eyz<3R%-SEFC8pI>wY`O+0V}v#d$(3AFdmw8KiN_%)V^+&^;zn)@n=M}5D6 zvI2dj$PK0T{*=v7$vuh{&qE!>=;J?Ga3tYY#}{B&gHui7o%}C?R=gy-s93_S5Hs8w zU~ls2<-{K>DZH@Z0ide=a5dpqfK{&o(6@{mgHr7=Zc{0C-piWXZA?y~$+itl!(x6ZU6OKm!!I69s=O2S zs<#15|GOxjOb6|C(qo-n9690UH>#ZC-<)S@R^$jq@{%av#1(=>f$%C8&Vyw zTFQr}4Da9ye}@});6}Jd^^{gav2G3T(>h_RtR6mv^B(_V_ot1K0GKHRxE>gO z52K5Bi#ya#!;P|hX3BMtognUT?6_pV@+nk;f32G}+-$oLU+?pUfwm~kzOvJ>hWr?36G3&`7DYTe@%E~mdht7 zycTT2BUmo)`*~^Dgh!}c-mUUVu?df?a(R!%3&%!1>;YKrIlM_0M|ivJr`=w`XBe^L zOr==(K8`|T@8g=h*ZO}r-bk#$*jqZvancFjgU*k?=kS<&tsjR2-^by=`r~_Jo`Utb z1J*N=j{81tCuH}Y!+PvshIy48glO+MWX^05JC5D$-fJyKH{5d=Z|2y>e??>Wcv!JV zx{~*Ca;U>Shf*vSmG9$ZktkzB5YyA^z-KptXA9Jtu za~Lsejg#$?RFaR+DHrL z?;gE-4iJr3;o~B8dl^1uScBi8z0Qq0__#!&C<+x(oA5dZ zGHNaJt}gN*4z{QxpMx2XEta1hGqw^#US06Q5LE$QS$HY6B_w(jMy<@4nB!A-WD0&9 zsL#$&%h0<|MbicbeQJH?^;tf3NxID<1%m(YGl3^QQ7MaCh1IXHvwZ}6dVjE1> z2}e$0oyZE+0%p4@BvHDmOK3}LE>XIw)ns?(CbE0-g>_R`u=hi-4OZRNX0mfRmLBR} zw%gxqN@y{D1LrqnPi712rFM~RCF`x8Qd^P3v}TuJlKZGJ73aZP`0)mk+iWws*;%c3C~yBV_&6VX|Ez@f@H&A{%ck`#V{( z%RVDp%yt9Rmt>!~>>IL89^3AFvQBQhBV=P;_HQz;%aoSNFL0wcWFNWAN4C+8nM~H! zZ5JS$>w0F89d=nr`w{aNmu1uT2H8N>oNQITjPo>g3fYpNut7Ky$yi>Z=OERd>{%tY z(^Xifz=qG$aa13yijHC3k72#Ef#*W(%j@BJD%qRK!p^|4C>|xECMB>TYH9)-ich}d zp2cdm#=A5155(N5hN}x1vsF;3TC7~lK8LMVou^jNb{BThS~WwhC);m;3Su$Cv`jl(|MpvumsDF_yCY!5L zja1?zvI|u{89p9`=RDP!YyhLoSN+KblPypq$=Z@#q^6MJ9u%}&sOFN*Wt2r~IoV;d z#j4uGYqmt)V4OCY>UJC)XRB&;vvDw%T{yDNRvXl9#=(B{K(JhROvK!Q|O?*~1so!!eGVj;vn_MRIex1Hq?M)cj7WF2h$d$-!Tpt`T z9n}*#Pp5QLMZsr*%d)=qw^5Ulo=edx-~U`n8?^&+8?`5CA8--nD`-8M^rSN-dQa|i zDN~{s0o$li{{6sHX)R^j?$jKFXB%bZHPnytzm8TpdD3o_%Fun)l96PQJ$YK z@(fzX5sw5#^PA9fDU+hjgEHno_S@+Fxn^%CXbwO0n&MMygKq;n92FDbdeE zf_LQ!Zpas0Lj5l4#~RU$Cwhs=#06UPi-{i*KOqjFbuh6lu@iAFt%rea)FnQt>N~z{ z$e$CFlRm`Aukp2j<{4r?;#lH?UeP~G973E*tR~(*j4|N0Hl_$6%KNYwncp7k5NN}tX98dHTlZgwo=ob?|B7Q;~KI*yOK*H^PJh?5t`--ez1e zYBep!-o}WQ##j-45NmCWiS3#glk2%VVoaj!h_OttM=kSz>hJFu^@PiQ9}>35Wq%0a z`b@o)(9Tisy0(Xs`#TQP5r+vBP89iK976#h2&SHaV#u#AKuqfA^EHg|2C zVM|hNT-HBSXOdKBmyHbd@+GNW3GMvq%ow`?ze;qj>$xxYzSI;oJ7z;~YQZsV*)eS8 zF>Kv2?8+F+M3gO-`G4o>@1&|)mvzh&cAv}oV zAG7@u>_0K~NNT3aZfk4ym&`i+ipnW2lXfB1!7{Fikm?#^nfQI3Q8BhFHA~HO+fB*u z?_{eBUA8ax>C|ksB<6|tWa{E$*c!4u$*c0_J2|R`Y_FOe><{)wYtyT8i@^Rwc9VZg z{van;edw|pu;%KYZo7m2Rh||qP2P0k%CUW}$J;`+uuQkl9qZtFoPT?&6uzHNlRwAt4b=!TF_YG{{ zxt>y&&guu(wk5wlwNQCG*dA)Yic|*KUL|$uruw@~>e5Y3Ao~DyIg;94T}md|sz48Q z1DRy&5A;&Ey6mZD!nV8ZB->u<-55&?^ybHjl3!j{R-lh6!H0`B+pIue^`vFUwnd=7 zdWFnpJ3uwV+aH-RnfC$eRI+tS@*AM~lgYei1qP~NE~^0>q|S2NNq&RX&s-+?4OZ8Z zNq%htXQ-#i>}*EVt7LXIhpKm6CbKzI9d_GEenVAD`5;5d+;$2St24+XzpjB{N`9=| z=GQeaLe-Mlj7F)$WHzHw%8QSz6y7UIMx&IUOfu>k7_FMQtOjh1YDH#eY@8bDGRbJ1 znnflVof!_XKYAdk{au> zWq!Wz7i8QZKqJ*;^Wzt^VP%^8BTNQq{Le+Erui zUL2UCB4jtIzlBx@=Bi6v7Rg#2xKKUdvU$Opz&uswvO}Sp1M}5~WH!I~>KigUWAoMb z))O;!dtiZbx^kSz@Akk#l}2XsTdZ2UO!C9KQZmVJdtiwgPbTC1d7w;9Ba``iD6mvr zNG7A+6|mW->d@JQ`T5PIuWOL2p`AO(3&5tW&p>?cv_BPVKOs$RUt+ zse0IDHDK%2vu-=dVS{?fWs<`N^(V3qaMaI9yIdW%He}Q}?Ftz({`Pvb>XCM(`kFR5 z>JLrZsQwjWK6RDybQjO-^KQ*9^j@XX$;5Mq=PGpynLSt4$S(!rZ-ale=S5Sadb+II zGditC4YUmHeCld7ip*wvwc1R!hiA2`)h;qQ7WDI8qxQP22JAX@z-=el-k_Ww(w{x6 z-JpV&$)4lgBnJG+S#4t4W;K#F8TEN-H>&fgEg+MbUYvHbxRQI}`TD47oNIgg%x#TW&i8HC^BkDzZ-lUSf3)3G}U$|^j&hqqMtI0S4%TZ%f&YJY!#-b#9 z%e{}q*wDZ#@8dCcdFm1MJM|dbU5{HX_IaOBNqxlpftGepD*2Zigh{)nRK#V{u1?KQ z@O)a`p5VD#{V~DwS#^}m=C@Y`PHpI6L;7Ad%we>fxYRk ztM)FFvAn6yh3>qI6FmQ{w!}O? zNqW zTAkqevAQ|tc}m9L)Lk*p_8EUy_a%6Ks&>abi!we_`(mEGGd@>uBzS(QK96~xmhqMP zKISO{8qJeS+e)cjPKMSmkkY^o$Zs%(EinKMEiGavr32ty{P(*;|=mbUT*~4P2Vx=%NHquO1om{I}1i z=fphol9Kdu37*ONGcvncQ}mHoyY~JRjZ0VdJ~Xh!pQ`g+CSys{oycsvblustC3`n! zr0agMb~j{X=&=dyf_hOxyO3TIYj;~lNM9CfcXvjXu1#o{t$!Eu{CP%>ektbp+l*ZO zrv%UD`Xe$svV8qXtX;V`UmuONTjgz`y{E;idx{Q_*>4|Unlz)Kme z^{|9?ZS;hg=UW+V_41hKdl~KYmITiZ`jwdHhZ!C9H!;sIGCJwJLGiJ4*5k?S8K_Xt zB(vv-F8U&C^QU-rq;=8dF3a;A$>^e2li9O&k$%p$<26c=4xKJN$oav^?5bP2tOl&R z?nP#=2Yc#?E|c>^Pd$rF&JUf_dg=L=;rx)6*;`-lddf9QAAJj%oU58;o~j=plXG~B z%)a^w%V4Wc>!Iy11c2Iwwas>ZY-92PB$~b+W+YZNq%yIf5mkkZ9&pb;%L1v>& z(4UeW)WwK0QGZ8fqnxe(;kHZmUXzL6aT}uWC+E$ZGbiZ)nT>LeKAr5K9)XOe=n-T# z%2YkddZJ1i-@-dW|DrWd;GV`ppTG`*b6&h5Fn&bH%fJy)j;m9fa& z-j_LD=eVo}Y=$l*vvWIBk9L{N?MywDOy;&l`Yc^y8Rqs^nI-y4*Hf-$X6x(8WNshN zyg=VWCUaYtS*jnh47RV!F4XexWi+hT z3-!5VlF?r>=jpjFs{vb}SCZL`7V0f7lZ+PXd&q1?i}Zt*A)}8o7wbQ|o|4fLT~8(% zeUVwFza^85zRz5$|6>_5TBg&7ab$eARIc;MHu%RPqjKHWW#=NJa$Q7bGpf*+*mj(w z3cZs|GE%|i`qwV20lQc~@3xaG&P()1E|ZKd(ch8Tj8^LZScZ&Jf~$0RxQuKsK6!1M zUa5PKNk+loYCW9HW>lreTL#;l^fh`WnVqAx`XX!dU+BpTuGQr(Tjps6wwlal6xGk! zcFZWMe;|{LItABh?+6)-d?wH-Sgo6r**UsQ_jj3ObeSGOW;5EL$6JPsdIm4om$;si z(G@yMCK>e)Ua4;+lZ?&?Zq#>K2HVKsRr&!kn^BG4Wo`bioN>V#{fx_wI%k8uNMCgoAp80 zQ!=_ye@rGBEezhIkCI77<-wbEV3dqS&SN8kTXYLDo6#-0lePIfdd3BB(cN9v!*e!R ze=?iVt$Mv}$2q!Hzf2|>tqk6#54fxb><;~z+fG*9T{>;F^u8Cz0+07D-Ga$!tcy)Yn;t zjBX1)pdWWVC8G!R(`1s--NA?STVyt)hxK90n9;BF*JL)MNA!QJ&HpGedPFCUk#TPD zKY@%M(V1j6qet}&GP~*?)%TD|MmvMQ*1vLD4cKq>Ubmgh(c}7kmq|vC>#xadM!WRC zEJH?*1b?SHjFsN)k>Ls5l}s|)6?{?;C9@elr6*X%jDD|Yk=cyu^g?U%_drHfi?Wb}0K8QscdHDG&mFETqvd-X(@Nk)71EHazXAM||7 zkkP*2bNYJMQ|9P-eG8dn^jh!*{Q#NGXrF$;3-0eerUOpyL;M)kV0%OsbWleu zLq`7${#7qOXA(M=fLm%r4Tvh}2cYQIL&FE8oqst_tPxUr3o6%?be#?+i zR_Js6rt2vgeWCwMCK=_2zSLil*^KZ!+SxJ|d-VQVXOP*9zR@kL%^$$3`$o5OSvFSP zH@b+-X7sJT#J1xceXE}#lZ@JgzSA$etOo2K`mb&~IWip4dXn_Mmq+g-I)lt+^iQ2< z88Ye;`j;N!dP+wB)}zTJqh6t-dM268=s$XqWt<~rD#>g{+FWjJ{#M9Hn`>Rx2^nd# zh0JDT%wgM(85z@UvW!zQ8W3{KK$q2kdCgg5c8-$FVwcGrC7DVxn~~qFw+tB-hmy@N zT~Em<#r&E~GCDJqYF;3-83oKAEn`M$=0h@@QM&os+Wf1LQM&o3%QhgRbmKY4R#(2g z$}khi?5fK!w~|Rl6GNHi9+%aCh0HFuoy<`)^N!0Tqh{tqGMiDh`NA?}bY3XOG@oMo zlZ566OJ*}_ZiZRLjPlJSGMiBgGt1ii*CC@8W}eG#MMf>mQZhS7EzJ|Q z9p|W}@l9=*qXnT;Ovq(5`3pj=O-C|2M{Ue-mq|u#%p@|KQCl;^GGtT{YG*EUJtd>| z=4vv@XjQ0#xtq*p)X_X-88hl+eotmI3Y&e_=AVp=!sd0C%|u3F^Dddqs55@rLUOQk z)Y+7i$sDZ<6`D0Js{t!AH;~zkx|xSvCK+`zzbCU9bvMshhK#NX^)O$$o{~{d^8=Y= zbVI0@Nk3P5w;A;|EiGe4eM}cJo6)JJpSAhtBcoHz87?bFMyHxlWHzI|X0vU_IqGZP zBa@773H397b6E}80CUuBC#&u>bINoX%U&KCPBUG|Y(|4jAIp%@w$SP3eAiPl8f@m0 zNk%^poncmy*^DCQ3d@+$5OXt`&1k6EW^MjGIC>8?zi`=0IC>8?kCNGpiVbe`!=Ig_ zVsj>$Wb|-on3>|T8n6-OA~HKiqs)~qlQ|k?ZYHxCjW)HGA*0`g&NR=vo|4fR^D3ES z^h{{1`GCx3G|qfu88gDa(>8-6<2%0bCWCB){|GV~Z*pDcV2;L{0y3M?1hdGt;~Y&e zzaf*1o)1kl&$z4xY?67)Z6|Ydj``MQlF>QFIbV9W8BH!z90 z$t0r#p>xgIWHzJero?TR>^&Gd&#a$iqYMrFEi}X2Un^ zep*ptK01bdW80xWpDHo`BCE#J8b`b(=CnByvs!Icb^h6A6q%e2wYtDuKz2}nh&z!= z%^a7VnqOy1%@>v>-{1U2uz$F=NAkq;Kd$Yg=C8trFMIKKP`A$hvzcSgbJ_XXADX$Q zl+3Qd3r!iB)WxSRG?$RsIl9p7v7Vfx3(ZSpGDqKp=9za~Rs*)ceCoE7Ia+AGb(zf3 zLgQR0W05&JiaV_F#WVi)Vvd4Yi%kp5@UA>BYl&$`Cf@@UW|f&DGN}umC@_7feCM(nuni_4-I#T?+3dDU_TG_o zjrquBLj(6@U27&Rmfr22dc9dkc2IA|r;|6BjbwID-DGO4Cs)=cvzg4U0(ojjs~`M= z{-EG9$%4vs(VO$o`(kieqXl8b_^C1+a}71K0md`|F)O^_u~J5 zA@WMpzhN#!*6IM(k5Rp|L|(#KK9l&H9MM>``ky|28#yt;e-~#tNBB9{u$9N#RZ7hP zuCAXxsvobz%MiJHG+pVjIWKgIg#NgBV6Gx8+W*2X#i zBt^4vR-B}0HjX(-(QKSPCn=hZ^Uz6}QyZu5Bt^4v@DC@Pl>NoV8Gn+Z**J%IRs8>a zU$$|+JxS4QoaQGfQyZttNs4CUY&=QPY@9n!QZyUqf|C@@#<}<;MYD16iyS9qU$AlT zlR_sYnvK)cnaG|~R`GZx*PQYcoBOuln9Ware|P-3RbtxsKgRz*p1T_=mZ$JM8lLrP zu2$lej$gkB;k6R49Q>AOK3*&FYK7kqXp7fMygK5Eq;9GJPsF!TL!rG8zaMZBevNHA ze(7vGem!72esKf$+^YllwSWVvD}IBboBAuB(EmX7P=CYI_@Ch!{I67R^&OtDKZ1Yh z{3s$B-B0;+f0d#KsB}G0h4g7EM-Ni@`gGMw4_1Zx4Ao6XR4+XQzg9XFaf|U=9>Wl6 zxEiQN;J=ahje$}49gxv#38Zp0MqRANsY{{RpvJ3>YJ$2(O;k7F%deZ%Bz3ErtnS1w zgxsyBsC(2@^>Z~%J)q82zrqvVzrn}7yYMvkQ+S5^88s81sLWC?s1o%uo*#Zqm8y=q z6!+kksgwiVvRKSZxma7du;3O@0MDCECY` zoUPWI&DmEtU+UX(u61h6S9$k4Kj`*ZPdXabI%hK@Y-Zcdi1}ydcKUCpemnKsslT84 zN8M-_X0`KZV*(LRjai>R!SjQj9Gv2LRqyuC@O+88`sP9YJh%$DBDltrY+lY>?|A}k zcX;+-48QUOA^Y${RQKoX!P69y#f$9gMfNpBXXd`^8KU!Z>pi3O`@s)^mu7te+?MqZ z&uV^3x0=tmJ#W+`BJgh zylv3-ZLi0XCx$(aJVWfk^M6OY0cUe|hOfE)H=bo}=EyVRkMiz)@$Us$dVG|tu|2It z@ZaGna{h@YK8u_;GhZ~#b()#w6aP}gS*GVxUIh6IjVBzTUjg}dnKhKJgPdn>qPyH_CJE5PIyp2BhLhg}#KjnvfebBpBeH?k3xsM~yH;*<2`5*cQIr2pN zFh`zZALJx^{|){6{FJ0Y&d@*}Q1-Is`pTS+NzzwQ(nM2idI8T5_6Kgu8JskhZAY7K z`DZ0fcH}vDscL!B)2Mu=n&HU0n&HTPF~gCyJ%^e()XbsgT&}}K)Gwlb5%tTdSx(Jz zYF1OTnwr(rtfyu@HS4LVK^EoS&A|5l1&ExfYLLq+Xyh(%59;7k6LmD_0m$+!xCi@d zo&R>u=4i7e?^S;vN1h8`X5R692U(sA@8igG;e8x=3cQaaPl5Mw$`wqy%kubw*hNUSNN{6F5l! z0vOT11P;>=0!QhGfn)U}zzO=-z{&czz-jt%;0*mcV2OSbh`UsQ6O8mb+1!@W0cYox zctW>OwQt@H&s`@q>xN(K$pp4g-GS{?e_$6C1@=~(fv2ghz+&|a;23;D-3@2IeBgO% zIRyOeUND_5$FoC^5t&t49kpSq6LY8S=7T2-pP zIa{gO=A!7gL4SVE)70$7^}_z_-Rx^O^y_nW;~StCvR|j>Abk$OXMXA-Y7W8Y)|^B1 z`36@bOH!4V5o)5N#naI;az|IHr*j-F(F$m7Lu^N%cJyfnpSN?`(Wkw>3ZA{8-=7_! z=MZ8s{fp^e4F6kmis?U^o|C9Ag&w~gOMM0P%YpM#ql{3kH>nP})wFJ+|5oa^p;fos zZPagP?~kx;9j#9jcf)5`?r!?L&bIZ`AEf6&%7@^yF!vC9IYiHob-wcCd`%y1q&|+R zRO@mbBh~QYS^AZ!$T8q)@ z=GT$6S%+4hoOSf9hV`l3YFgKG4C`sVjGo&V zXPYZms`qoZ(Q`X}c2Hl(IJ*%ikhh!GXQ_W3xIg<4^u6;A!~ci8uc>z&t{+G0<8egq z1#V2uqNbg58|u)W`p%A2wKw$pvx})8M*VPlj;3`IXr1b zC2ogxN$L(-chb6(`Z|nlKdytM-`$L}hn~;Uv!2#^S`X3sKJ_0n!pGD*9vQzE|BC#| z)OMb2YIxjGQ^DOm;C?9fViS|C_kLl@nx2a`$j#nz8-)%2`p%xd~vMxSkzcQC?E z`tPKF9dS2X?Pjap^n8}B>S;Yh>mgbX(fU5+j~VA<`r!8!QCm%Pd|a76$;0u1Le*@WKEw4v6!C4v=-BIIOP&rOKB~orj*vXlotT!r!JsR6h8a2qmu->3XBaDM8?^wCKoJ4vh~)M&P5)~8R5Q+Hl($j8&6Oq24$3=$s0`ygP25e- z-L&pzgl8!qr1cQ3hp0J3>-&^H2BIePar~@?pVjcQ8kE~n-_Dg;4a%K?sD_{W3w?@R zlnBL)Fr1#V{W903w3bp+O6y$83m9hs<3x$o^sJ_}nx2t2;fX5;TAwA>Q-6s1L)5%a{1}Kj(5jLpBPW@4NM;=<7f|1hay#lfP%d^+Jcm;* zbx|~PDK7wG-Wj1fxh?8*S+dmRO6sqqz83oZ+1u#9gSZ=-`Kh}pKTCWbI6w7y`X8e8 z5cTg9ofOU>etdUjs+ZV~*nwC~98N5uXDQ{m#Au3ST}}BiVl6e>DDOy-(biG3o0@vc zhbXI5Rt&$mvof`Say!aHC>K+nO}UivI?C0QYw;^H`?I%FvyGakDetCykn$nQhk^4` zHGV?^vlEcM+E8v6kb1TYNVOx7=cf*#zL;1-oJ}kxMv3c))d4xjRihP-QH)s~kh4QA zty_uPh;_uLiMxsQ#Dl~`M3p9E(?o~ZhS)AmMmU6Wahi;LHsw;vQCM*tpr#t~{M2gd ztMMxaFJy0}ejBkMU96FG>7|4iCDsz_i1oyh4DqZd7G$zjCR-7s#9HFkOgWC#QLZN* z&Xk%QhW>}VHbEI}`=Dsr2j!|`2sN{b(V#?LN4b`AT~K=21J57w>M0+j^)NLm#QKCJ zrY9sm1=O^mrad(gYD$Q6sEJZu4|z%IcH-0293<*2iB^&&k!MqmQm)OCs@77jqg+S1 zo~W9MRW*}V1;hw75y~aRIrz74a2BJivgt{T5TnFeVjXc0-nA^t+mnr})8_TmD7^c5 zA={H9dQVQiYSz3UNBS+GzI~3Y=LqEzVw6}*tfOa1uB?IWx#GEpSWiv+JQ>@1VqKoh zLS3HpwFer^J2i(X7c>`ZL36Q2C`Txl5TnFeVjZ!bsPdUFF+!|w!CqPl*0z0Jy_vnf zqpXVc9XT%@rQf=a^yw&V>xrrp<853N~|N+6IFM5 z5+lTt?y|Z{D9`CGk>_-m$WiK})YlU0sHvk|Pr075>cRb@2O|?B#1djHv5r_zR6WJh z(~~Q_Cs#N%k)9GKLb-%;3FRoUmYQ11b(HHU*Hf;ita@<_#0W7;tR-&mB|UEMB|X+r zv!@qlgtF?*w!OKpQI1fKP%a@xsfkjqrCdw7j&dF4dZOyXXvATCq~BqEq~DT0GRq~@ z&*>w*M=945>u9Z`Tu-^4vO1N~h!J85F-oi@))DK8hfkFr51%SMs=m_J(^vY6^yM0( zri2(J)>2xpUrdndLZAbqtTAbmxs88$%rDxn-D))MQ8YM}J11~LLMLM)-a zgmRQ}lyWVxj<{!_^tET8^i@yI;epbZI*rkY5n>53N~|T;pCrR*Wb(HIgYOwfw21|U;V2NKa zSbPeoZ$DUiiBJ=vri2(J))MQ8^+a_BdnZPSCB)h@BxWt;?Po||+s}}`>ZsXshV)WT zSw+NCMHq*20p$p>gcv2(66=WdL^Xu1h!NtjA=1~dA=1~JA<|29h{TW5T1%`W)>B_k zSqP>vF7iFMT1QLd+4 zPgxCP@5BhPgcv2RA0~aRA0~a(QnP)S^i@Z>o~VXPgvfB|H$u6D7$w$HUrV`;avkM* zq8h>8iS0*7U+qUoUlD4CjgY=dC`XC4#5!U53N~|T;5!GnU-Dvs~Bg7KwODNA7ExpVcExkmkk5a#W zwDeU=xsF&*RA(|8F+waMMv1k=`ZJ~9ddg~y_I$}Lhjb-n|2(g4XXRKVKMk%kSyq#D#R^r!DUr$uy7-5{~3n)h@M<|yNqr~;& zc=a_-uA*zHsUz;8eh>6ZQtPQXJdX2n79$fQ#1dldS<+W6Y98qZdg3n)j3 zCB!JPmRLvJGhRluXFPkS=J0s-K7nzF5n^z?r!BLC#2nIcYCJ09pi3iyIXvp z=u|o{I~tqI%;lm{alHX+PWrGeAvOr>XPs?=Z|j z{m#b^2+hPdh_i67O$j2Fq9$|jUE)P*EWSCEp9c8S{}Ar~-xm^mG+FS;)JK79C~qN- z2|W(Y{@f>lzxRkw|2)C9)EvqbtCgqci++FZGr%=@633VQ2jDZ!1bx~2C<`{Fx2-H* z?s)~CiJF$4H)EOu&YxoPr_RBcJks-iOg=wBUg7y9rZ=9iVsf7Z`5`B+uS<|mPmsqa z$cIea|Jww)d4f-u1bJhEd}o4uL4tg7g8XVi%p~f^HJ6%P*8Ka}_-%b!dj1*H9B_0q zJmG*fXt3_QSdS?{gSD3gOoz^>46H_j6_^GLf#FxGW|Sed!N z4p^fGcagOK7Q)M5Ew%=B!#Xv%o2wo0G(=1k zed!In4{O)pU+d_HzJ3lgxNBiM zf%ElnXchpCx>%0{{!EXC<`SS$m+3LU4SF0jmjltS9uK@xPlVI>J>c;_^O@_&1*oT{(}3;jH=gjp*aXN>N7nL z__8 zuk};{2bwBqP6HY>%B%&BHtV1{6KK>_e3NR_G;UD{Ki9v~yYw^q1^t>np#Q4>roYlhaKl-O37LG;&U7)o zO~i~eXPI-%3{z?rnhLYZtTR`bYt7B(E_09hrP*WNG@qL9%u(ZYLe3N?>g;gda{lIg z?|3{po;y6h@Vw#4@^nf3 z0nQd}P#yf6CU}j;-JEA)50w3HEY2n4@Hz{x@pw(ZYa(7}<24Dd$#|WE*A%>_;x!Gg zbMcyv*Lir&!0UXxX5uvquM)gw<8=Y{=Te+u=Ag&9=P?=mg=O!Z4{mBKGI8L9q* zE`J!?d8*c#r@q1~fCr&ldDf|3*!J>#fmgK}>$wWsZ`2m>EuOF7^No5L+g6^(RR`~1 z)JE^)u&>u0u#&b4 z#`VQcycXjc;{cBAi*dw1fFu0@9On<JYS6JFUGNaF^=ThQQ^06 zt+8E7IjDG1*^;?~+p9r?OJ~g*wxD9^qS-5p7tOAy=+%2x4`>I>nnhvc+~q?S&6|5c z`RoOylUFXCJNN?EaC|%4?6_ck80$FYsiJHwZmi#)joW+Ag5m7Bv*!$+GYjH5ODa|@ zU0PPYeD0i*p6aX>ix$nkV9{KNql?QHFP&Z9z=khbv3PErEn6{rd4oxUO)X!rTv|<@ zJ#XIJIpPc=hVe@lt(>%U_7aIW9IX~DSiaImo?A|xjk~-|*w_UX%dr`DL2=oV<#R6) zc|`AC>i@KNy|Hl|*M0VQ$2*eJiFdLSJ0aNvnidXXkrG8Ybjm2EL{hqxq$rV8)YbsC zyj$`%I^Ldl_arh=(7VC`QXm1CLII3I0W2UwR8%SK!a-5A0g?~>2e?4mPyJAT=%;>a ziU9f0e~A10y_vmT@@QMBKNZN4w=?tJn>RCW-n@A;JG)oLcO75yTQ4_46V6i?)t7t}hw5z<6~M65h{4p?3iwE+0cuU?sstmw% zl4_djqh^-8YOC&?R}f*v3EdrM?m{v?eqnWXZ5f3(eH~lf3qogSynF?AqTFaW{V4D*zF1s33|E0)cCYM5K}t1pTlf)rMqDE=D9*1cAUb1X9y95)qm+ zFBr~@2jA*5X zn<$}ko6>6ts8Fk6byJi|BCtrx=)y&>UUw=~`C$B#1C?+qQrw(tZ#TRkbSvemswNX; zezE2IP?jaTVPinA)qIRS(9N8$Z)~^?H+1cK7f9V#I@{zPh0Ywjci=!^~LX9%^BD$K{ixPG01+PLSd!dm^_F}YB_QK~jkANjK ztrxrG1OXK8C`4HEs>}Ay5x51%4qLu+G;#%V*p7p-c{KV$%dJ-(UuNYV{k-OYZ$oT% zZ;i@V&FK*pG0=VStY&w3>OFipvV{&bTN1(uH!Si?Qus7H0UL&-3d*HLprqigZ zHMeprSaJL%x8i$&Q}F<6IAIXljjHVf@4-%R;;3U{Q5P}1L#Nyz8p*(G`3NpK;bl9h zUG%DsSPauSYDafc(nY}J-ko%n6GzMRioAfXf=rQfUQ42wvSDp0^~f5- z5L%U0*a{%aGJi`Q*o&qzkwTz8-6&00LLJmrtQwN*fHo-lH(lLO4YKBt>z!f8ujvXO zfhn_|;{MDeCTTq}k012a9%#cXJ*8UsEo z>uz1=pi`{xm8~tf7ax|bI5^|8+uOdg4aUZsIYI_@($$78Ydtg06?9A#Au;aNW^4nX zq}y;pwLwrJsUw#v*5q*=rAFVzfOg2*t)fn9zUpGiyWo3wMCDgQ0%y*j+1S9yLbMDc zjVZq6+x4#6sM#QZWvK5hIiU?M_H2mX3g2vz9Slab>QrM0U1zuM_(sRCIj^)_|0n{P z=}}}N@BD71-m1zFn&8geF5=-D$G0z=rXaX7akMU;W8byeUUUScPw`*aHTD|2q*$?%AZH(dX zEgCbU$E4ACF)P~`p+%}E^B5}gl(oSWKt@7;mYK4Y~r@ z6Hp6vT;>}UuZkHxGO4DH<7RXaL$}0d1XHDniA&(@n$&7*Gtd+X&nAGMP;us)UZn;O zJ&5&&yQ`6NP~vz-B4Tw*P6BHhK^ zP7`}jSg66G*VTH67uzK{=t(mYbhTbrH+JfZZogCm?xmE^P}de>cI+L~L+TowGjB&x zPzs9z*;x_yPU{WWICevM&5cXQ#aXkalZ&us5-$gfZV0nK-@pp9p`e9vf?O}S+Xl7f zU3PX8N#o}j*OV@gGJ2w_#^$kL=tJn+vb^o8m9u3Qyd;>dVopYvs3rTBqdj(oNnkbF z^}?*^h>^tJk9Nbaw8AS}X!*7i<5usuVWk$^=@?UPK>yw96-+r|hhj{`FNSs*Tu7`** z;E`7Y@@=ZmHVC}1hO6ug>F&o`!B-m)1p*F#u{frJfJi~&+xqGbclZbkVZv@Z*f8{k z$D((KJn9les{l;vQIq1CrMvww9+APLm`VC^W)1Nkxf8kQ_$G*F(f_yUOQ>;fIp8Wm z(pOdo{aba=63{n|D!j~%PPY<7>3E+c5UrQJi$IB3Ogt(mHYl>-3Jw{gh+{MyWmJ33 zRqPwN6{lNZgx1rX<9G4eRe^QnU=L^_W#;VKaF)kj4B%4g5F|RXjNMcn+Z2LmI-*?; zv=YsnpW4_6Yi_q5iH48UVVs5W+6#c!Hq+Y*4}xhRW!WkALdW!8kg+ZEyP?ydm(wjG zp&VV)rn!r5=>bBqYd1GauV9J@ql6w6Aks^;%T68I3=veT^r?_{3*!P#H$ahNtv$y8 ze!CB=1PrSl4c9=~(Rw_gG}sy!wa}|^b*bf6O*GOZlVq=X0mh0+lXZ6$9~oPNqY9g7 zSB1oBR5D3n>)c>j26xgEJVmmyncffsh`ztF`9*BGsa0(6A}|gPymu`AVL%{)NC6XK z?~X-`oAGN7)@g@^hN?STp%RCP=Cr)itYfkZG2gR0edq*zBHTy7g>A(ypxvs6R6#L3 z>hOvUlgMq?_ZsxiyP`g-W@fW8S;N>`nElD4@{Otj8Vnc7{85M9@pXOD*ukiP7@onjNEHcWvpsK=m{2+O&hOHX$S4v#sDh%O2jW0Nih0@5+IaJgvS0E-vI&LhhDG&%+(x zlH_a%7h(vZoY@D=cLw>?rHJccPOJ%gBmjLAe;&An$X^9)6E!I*+#f>w*3>f2mZ*Y!!6a*TWwn>RDcS$65EV3m$tKQ{cOV$kB&ZvR_r^d2m(F9)@oKs^zo>P9mp5 z6zk%$*T4xcz&@eF7``g)RVQ@Vg`ZeKxgP4(f@IMjA3d1v(hX5Z*#l7MlX1L@Kfa3G zKI%m|v;X5%muBDsO7hskLKN%bGG%HuespOXQZen!tP70SE-cGY06jjT!x&DDC0vIw zyo{4OI0XoLhB18Iz;zhI%iw}jf}m#@!`BU5hh6wUcT}Pu^_Yoq-BDDCVll3a+Q^7R zJ{^m3>s?$F>*BHtrrtVC!gakD4%XYH7HPer_La~tv_vHXqYa_9g&3`Rdr{>6=S<`B(c0v=HdUbS%6g#Fv&@>RBK~@I?IvCRV z3M`lkKz%@%)EO62x!C>@N~WF^uR?QEB>p=<(j^>(0bqmx zk_?oTL1jv+*!~CIhoiciAEBEy-+Y(vJGweIkXDwP4lcBe0E4YFN7wT7~#RO%#T!jjPc zQc{f^sSF?})QLgI2&PVqK%g4}X%f=R52IO3kE!7?l>-ddtf}S@Dy*Ypc$brvfuJGZ zjI#2hh^O-TJc<}oB*TGI);`mp?aN_=L4r9_C6%H(s$vwelTg}b2nmQ}dRlA($^ z!LFv^k?hC1Qb0kh|6R!4)Fy*m?Y3!L6D17dyfzHTV7ebRWJnof62%`P0xWD^YDAcb zfn#>sg1&wHC?)Ot;YB1YZZ2tf#=qGi&^DGn_aZ#I*e$|)HkBp#g zgp5F`D5b~XiKa?t!<3KEi~~{Zupu&h-b@ucQy9%0X#zF&uQLVv*N(8X{3FlwXHzGU zPuCedErEkz{mh1LyX{EAYhP1 zkGx%|i{`!!RGO$XBK?fWWe}-jOdUhyI3vdg(1fo`VXWfMBnF+2qUnB!7wUv|(JZi1 z)IW~?A3+P5=RYLRu@db*Ed?`x1l?eWj_ckrXmmO|5oJTGl`3{ViMVJu0C_O%q=jJt zJdoub>bfqBB2y4aCx?&~`xj_CI#62tW4S(H#V{D#4`h{iN7Y-``Q}hAT<=j`AU~yOgl>6&1F+a6*{ML zkj-NYks%QhXbYX^p(z+@5YZR2&-KoE$+_)doC?>OE_P;$otKK8xnk#Xv9nn0tQ0$I z#ms;`y{gdOyyqf0}Abxo&Pe^K1g8V2fy&4_K(b1vTLi;^L`a{*1W^gw;e~^k>vc|<<=goI*00^hKg@>Cb zm&yDls~0Um$dSCXqz@ukNVa7C%4zg~_BlE2!XuywVwCgvFy?_$Dm9uJ&9Gq%(Ihwr zM51`4+^L03`~io({njHFAv3**1e91ZUJK#;uid07b+;6v%+k* z#UFwZjdu>}Fve+Q0491gLyMdRh%rvY+H2rMj8c;1HeNKhc~#Z;S2ybVug!%SHl?qepl1C zi=DQHGXR`wj{b>N3JFcRPwyF3;lydoIel%Nd;g%FHwf?}9z*G#m}KfJ`?`HkvwQ>> zUFT;2>PKd1+|#-CB^O74c5GxfmeVW0Q-7tYmjMAkp`n%BP=G@N}M2DMUt@ z8XZAu2ocQV&tbijK@6)2ULOLJ>jw#j1psJ0$#wx95&S*5?&t8EMD#ddli`c3r9Scn z-)=5@jqb4koTJBiK{#RJz+m$qFY+E=o?pWu5;?2;ygB#q+1r!jXTTx zfeXx1it>~|dJ+#s;t8e7EuM}mE!vxbQg}&t7H6g$8>bc(o`*_Lo}R@1vTdoC*J@5F zadf04M@LHLu4>7}eLs18Bq+_Ul!MZi=NpOucgu0B=}U6@VFEX%lj)M%C|&$j?8ma; zGvlZEr_|>x^%+T=@+)Ug)x2=a-97uMb1$AdTYd4xvoCBpo0aLQ%G8UMt;*!N=@(zv zvd>h`OjWn0s`k{Uu`!QT{ZOK+BHCvY0CS|()LqIuj$8b^EsFy=xEuR?EexB%XC@}L z-LTf$9Itpg6O~9*cmgVzNN|JKOotL)CH%*6OMNndGbNd`2sqDhbMjM(r>i0-)I!c* zx74e*_zP-lspGSCoR?U_ZBiFf1z@1uz{w2UG_I0t@u?>w1J4iShF876D?he(xD4v# z2UP``kEQ8SAI|*l?;e%eI!t!#2`UJ!7jIpmu$MsJTiDlue}bB_L5DJfk9;WHTqcdqf z&XVTyQ)xcHmgYk*eRzPU50Buy+xx-YDZaOXA1o^wn3Wgx)1dIPY8qwIvH~S3x*xxa z7=Qlto&CR7*3t^|{wcoqKWeG_{~6=SACK!xJC~oa)bfADIL5ffO@6Me&aM9V;={g2 zfALqBzWc{F!>|4K=V6I(t$_%Se}TT|k_lAEf{N=d^PAO9#Ji@vH@k(6DSkd7xz>Q?rcwYr@518LD^mLNM*5$)ZI3#|_ttwky(KiKaT-GZ zO<^MrGEo1B=i@CoeX%1uU_5gG_XOt_cuu1PuH4SzeOQ*tJ+e8RY$zp8HWob|YT{tIXSWrqLX68K-l-1bBO literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll deleted file mode 100755 index 94c8e2f09b60dd76c2fcbe27f95ebdf5f86741cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66048 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 From 76194c2849801a647f18a491101ccb7aa3115a68 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Mon, 27 Jan 2025 10:22:51 -0800 Subject: [PATCH 165/223] Revert trunk branch versions to `1.0.0-rc3` (no hotfix) (#223) ## Description of Changes Remove the `-hotfix*` part of the version in our trunk branch. It was a (my) mistake to merge a `-hotfix*` version change. Hotfixes are, by definition, cherry-picked changes that are going to be released directly to users without merging. The consequence of merging this change was that the `SDK Tests` CI job started failing on SpacetimeDB PRs (e.g. see failures on https://github.com/clockworklabs/SpacetimeDB/pull/2137), because it checks out this repo, which then tried to use the `-hotifx3` version of SpacetimeDB. But the `master` branch of SpacetimeDB is at `1.0.0-rc3` (no hotfix), because the hotfix was correctly released from a branch without merging in that repo. Although this PR reverts the version change, we do still have a tag `v1.0.0-rc3-hotfix3` that we can use to release the hotfix version (by `git push -f origin v1.0.0-rc3-hotfix3:master`) if/when desired. ## API - [ ] This is an API breaking change to the SDK No ## Requires SpacetimeDB PRs Should work with `master`. ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing I claim that the CI tests passing with `master` show that this is correct. The original version change itself passed CI because it was pointing at a non-`master` branch for testing. I claim it would have failed if it were tested against SpacetimeDB `master`. Generally, this might point to a bug in how we've done this CI: We should probably only allow a PR to merge in this repo if it tests successfully against SpacetimeDB `master`, even if we want to point it at other branches to test in the meantime. Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 4c0eca01535..081cb2dee3d 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -17,14 +17,14 @@ README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk 1.0.0 - 1.0.0-rc3-hotfix3 + 1.0.0-rc3 $(DefaultItemExcludes);*~/** packages - + From aa6cb5b5cf24801bfdc111fe7050aa00d6ad2290 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Mon, 27 Jan 2025 13:14:55 -0800 Subject: [PATCH 166/223] Revert DLLs to `1.0.0-rc3` (#224) ## Description of Changes Revert DLLs, which I should have done in https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/pull/223. See that PR for background on why it was necessary. ## API - [ ] This is an API breaking change to the SDK Kinda, but it's a revert. ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite SpacetimeDB branch name: master ## Testing I would have liked to say that the current CI is sufficient as I did in the last PR, but now I no longer feel confident.. Currently the repo is in a somewhat inconsistent state, though, so I think we should merge this right now as it will not make it _less_ consistent. I'm very open to suggestions about how to test this properly. Co-authored-by: Zeke Foppa --- .../SpacetimeDB.BSATN.Runtime.dll | Bin 66560 -> 0 bytes ...{1.0.0-rc3-hotfix3.meta => 1.0.0-rc3.meta} | 0 .../analyzers.meta | 0 .../analyzers/dotnet.meta | 0 .../analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/lib.meta | 0 .../lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 66048 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 11 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3.meta => 1.0.0-rc3.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (91%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/lib/netstandard2.1.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3-hotfix3 => 1.0.0-rc3}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll deleted file mode 100755 index 5f280ff20b9c722f63f5581da02801b8d27c887c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66560 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 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll similarity index 91% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index f651b04369b3e1e2e782ade23cff5443c37d9908..c1ff8cd98ca05f6d80ec38a77ff24a0e9692d496 100755 GIT binary patch delta 1844 zcmXw)ZD>#NJ0rD-n?+_A`eCw2EVG+)AIcosig5|ZU}b_hCb+rt9O@1C-~auc z|8t&`n>5$FshT&{&px(HY`^?v>bS;ErY>w>9(o4Q3-Vy_+>&arRXQ0|;-&o`fOkcM z(kgbab!=RWv31IGi};GY$375Dv048-i)+L;^MTA3rPI%fnWLRoTG_k^8E@L2*0n(b zN_ZO_fF|w*4u&{wgsN)lkD%XX7exLrbkBzRDIyt3_;vUY9#rR+w48hrV)ZkWnWI&K zeit*u&VIeh;4UV+xmXg8i6i~ZEG;f!^#?JB{=WFP-!+=9pJbn4pD9Y_Flo_pL}rN0 zp&GovCZRCI@Mf#*5VTU&D&Jig$u@hBRZeIUA47jo ztQhKOI>aBMKgA1_EKsswt-#K#M8J8@O0X&hhq_B|aaP(0dGYm7chfYL9 zUM`2eQQipCdY;HbB1IxlL5nM7#!`V9(L1b%r}Ze2IFhTnNtrPshl!+#oF$U2prMJ} z!0JwWUJ`L>*kLocvr_hNsFXZdDf!*u4z?&(?4Dtz;@91w(P=%nN@jXi$q6Im$nQo8;4^St42TdGdMkV8agL#E66C#Pmore(=AI ztRFSFStC2ANzc{Df1Yd&y+@_F)5E0fMzS#^?MQ!Dd9@)6<@@^RuO`84S{B1KZC zLw-@#I0PJei?4As!fm|=FV6EG@+OtDq($VncoF#`ht+a>%WAqEtAAtEAzp%a@-*K2&qZLB%hW(^Xb0S=9N$WzBcjV{gTa7FTOwZ zM%Rihu)?VdJwoBOr>F>gzk*X#DQw|BPpxxE38+aK@q$NGF79-rZh$NZkC zKibjn>*|YVTJAhmJ;UE_mr+be$d~d3K3EmxEg4lZJ?UCoFuKaiV_4vi)?m=As@<>YWOf}Tv zlVtz=c*?y@EMM4ImA1SL0Hno^g)!&lXvbG4 zo_%=bg#Z#a_#uwheu$y^paYo?3_RmV{CE{bjUw+y)`gjP=BK=$i6C29_892V_eED` L)$f0?l)LnQa*YUP delta 1839 zcmXw)eQZ-@6voecZ_C)$@v(MvyS+Dby)ZJz#zwofr3Slnf-`Cf5zRtOT5ebNLC0YH z0a4jq28nzmIA8cj$mlYLpfMvhizc9!bc^6e2mvwj5js1gCMKHb5{N-P@5yM=r_cSJ z=RNPaZ?|6anrvQ^-+jk&BEI$U$Z?g8j$C|wN&91fD2NvWn{}kxZgZo-OZ5@JtGrrT z%RAT_c8(9RHImKBKV+}5w>gvS*1yMa4IjJb&uozbE$sKqk-(>GS%J59Zni(EYJgr? zqBOt&)GJ<4AjMC2ww7tG!|1m;IFa8vwWc=L1d)s&%2jw19+u}8w1oUH^txs!bBk8_ zlR8WB?MbaHrRYp_)7db*#}6lK*#$m{)f@a4`k(oeq&|4THO`JRP_AU%VeNn##Z8ir?8SrUCL5{FUEE{S~|s8L5XWpvDJRdvdEsoE+y zKfBW!IiN-)(LX}fcC4n9_=1Z52ChA!8dM!1ZsP7y#}IWM#_9zBWv5m(p^j4~OZ+Nn zPRz!&F6ZC@wLn!S)6BByAj@J-S;q5m$+DQ=jXb4PQ$|OAS=EWR5{V$eX^FJSr!n6y zdtg9`FDOk*oek=2VE(3Rh&<19X=OLnVOl#bI`aoz&ef099Fgmok2axr0ye1g15 z{t)?T(mB+uW+@lyE*Go9q_J`_LyWvh-XxzU%@WCy&y&xS2RnA)r}~`i8~$-$Eq?Jo z^sO6ADQ1P}oF+Y2A^v%?6?Bh8^5pa6VTDM#SBR>c{HhfqA0{6o9wVP1Zjw)vo+C0x z>UN4hlvPd+M_*7@IX!SkYr~64rH#Bvvyd~Zr!h^oif2s~gtP%NejTkpfK1OO1G0CTe&z#sZ^5U}p4m=-P`{nITpH(e7 zHhbfXx=iDh&#N{*$6!NKLt{f@{a(Xc-?e*RvU|U`t~uE3O$3A9mSpD+Bj7W9K_h9b zZw>@olJO>^$(Km_5^X%y)%5t{f%XpEKe%{mw3nhvuqiEd|$^0iT1!L%kM*o`}5v-J#@it*au1IhW+4$ zI%tL!usG+{M?S3={ceh6eP=UZ6u SpFmH&bTG60r$5+8W6}TDzzCuM diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll new file mode 100755 index 0000000000000000000000000000000000000000..7f155111f04ef228ad48c64817fb2f15e91bebe8 GIT binary patch literal 66048 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3-hotfix3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta From 82ad0a069f853802a7707834cd6d293ba0039073 Mon Sep 17 00:00:00 2001 From: Zeke Foppa <196249+bfops@users.noreply.github.com> Date: Wed, 29 Jan 2025 10:51:26 -0800 Subject: [PATCH 167/223] Bump version to `1.0.0-rc4` (#225) ## Description of Changes Corresponding change to https://github.com/clockworklabs/SpacetimeDB/pull/2177. See that PR for more details. ~~Note that this PR only bumps the versions, but does **not** update the DLLs. This is because SpacetimeDB will likely have further changes, so the DLLs will just need to be updated again (in principle, they should be updated every time we push to SpacetimeDB `master`, which isn't really feasible. For this reason, users should not use `staging` without having their own copy of the SpacetimeDB repo as well).~~ ## API - [ ] This is an API breaking change to the SDK No breaking changes. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2177 ## Testsuite SpacetimeDB branch name: master ## Testing - [x] CI passes with that branch name - [x] The branch name has been changed back to `master` after that PR merges and CI still passes --------- Co-authored-by: Zeke Foppa --- sdks/csharp/SpacetimeDB.ClientSDK.csproj | 4 ++-- .../SpacetimeDB.BSATN.Runtime.dll | Bin 66048 -> 0 bytes .../{1.0.0-rc3.meta => 1.0.0-rc4.meta} | 0 .../{1.0.0-rc3 => 1.0.0-rc4}/analyzers.meta | 0 .../analyzers/dotnet.meta | 0 .../analyzers/dotnet/cs.meta | 0 .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../cs/SpacetimeDB.BSATN.Codegen.dll.meta | 0 .../{1.0.0-rc3 => 1.0.0-rc4}/lib.meta | 0 .../lib/netstandard2.1.meta | 0 .../SpacetimeDB.BSATN.Runtime.dll | Bin 0 -> 66560 bytes .../SpacetimeDB.BSATN.Runtime.dll.meta | 0 12 files changed, 2 insertions(+), 2 deletions(-) delete mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3.meta => 1.0.0-rc4.meta} (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc4}/analyzers.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc4}/analyzers/dotnet.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc4}/analyzers/dotnet/cs.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc4}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll (98%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc4}/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc4}/lib.meta (100%) rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc4}/lib/netstandard2.1.meta (100%) create mode 100755 sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll rename sdks/csharp/packages/spacetimedb.bsatn.runtime/{1.0.0-rc3 => 1.0.0-rc4}/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta (100%) diff --git a/sdks/csharp/SpacetimeDB.ClientSDK.csproj b/sdks/csharp/SpacetimeDB.ClientSDK.csproj index 081cb2dee3d..20c5a709b1c 100644 --- a/sdks/csharp/SpacetimeDB.ClientSDK.csproj +++ b/sdks/csharp/SpacetimeDB.ClientSDK.csproj @@ -17,14 +17,14 @@ README.md https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk 1.0.0 - 1.0.0-rc3 + 1.0.0-rc4 $(DefaultItemExcludes);*~/** packages - + diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll deleted file mode 100755 index 7f155111f04ef228ad48c64817fb2f15e91bebe8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66048 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 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll similarity index 98% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index c1ff8cd98ca05f6d80ec38a77ff24a0e9692d496..350d2360afa5704eb5115c84adc06b676f072bef 100755 GIT binary patch delta 244 zcmZoT!Q60yc|r%vf>~cTZS0w{TVRT=>`P7MBaRd1WbxYTs_1Su*mF`+%S7AA(l{|S zDKRz8GC3v9JTb|_AUVy*)X>u0GBM54%plR&DAmZ=FvVoE^0lwbEY*6~S5B6>6(AtP zX55lkV8LJjFaydY0`(dJ S^%?3-gER#|;D_{G{%#yR!=JsTnTLA)3 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 a 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 X^S(8JZ3#o(zv9<*{p|DqP6Pi71Qp)r literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta From f4cc0b33d628ab25582fa4efb22a5a830dc10e1f Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 5 Feb 2025 18:01:49 +0000 Subject: [PATCH 168/223] Improve CI caching (#228) ## Description of Changes Use SpacetimeDB commit hash in the cache key and skip rebuild/reinstallation altogether if we got an exact hit. This saves 6-8 minutes off CI time on reruns. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs *List any PRs here that are required for this SDK change to work* ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] CI testing forth and back until it worked correctly. --- sdks/csharp/.github/workflows/test.yml | 29 ++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/sdks/csharp/.github/workflows/test.yml b/sdks/csharp/.github/workflows/test.yml index 460ab97789a..46566d41161 100644 --- a/sdks/csharp/.github/workflows/test.yml +++ b/sdks/csharp/.github/workflows/test.yml @@ -45,6 +45,7 @@ jobs: - name: Checkout SpacetimeDB uses: actions/checkout@v4 + id: checkout-stdb with: repository: clockworklabs/SpacetimeDB ref: ${{ steps.extract-branch.outputs.branch }} @@ -83,19 +84,23 @@ jobs: - name: Cache Rust dependencies uses: Swatinem/rust-cache@v2 + id: cache-rust-deps with: workspaces: unity-tests~/server-rust - shared-key: UnityTestServer + key: ${{ steps.checkout-stdb.outputs.commit }} + # Cache Rust deps even if unit tests have failed. + cache-on-failure: true + # Cache the CLI as well. + cache-all-crates: true - name: Install SpacetimeDB CLI from the local checkout + # Rebuild only if we didn't get a precise cache hit. + if: steps.cache-rust-deps.outputs.cache-hit == 'false' run: | cargo install --force --path SpacetimeDB~/crates/cli --locked --message-format=short cargo install --force --path SpacetimeDB~/crates/standalone --locked --message-format=short # Add a handy alias using the old binary name, so that we don't have to rewrite all scripts (incl. in submodules). - rm $HOME/.cargo/bin/spacetime || echo "haven't run on this host before" - ln -s $HOME/.cargo/bin/spacetimedb-cli $HOME/.cargo/bin/spacetime - # Clear any existing information - spacetime server clear -y + ln -sf $HOME/.cargo/bin/spacetimedb-cli $HOME/.cargo/bin/spacetime env: # Share the target directory with our local project to avoid rebuilding same SpacetimeDB crates twice. CARGO_TARGET_DIR: unity-tests~/server-rust/target @@ -129,14 +134,6 @@ jobs: spacetime logout && spacetime login --server-issued-login local bash ./publish.sh - - uses: actions/cache@v3 - with: - path: unity-tests~/client/Library - key: Library-SpacetimeDBUnityTestsuite-Linux-x86 - restore-keys: | - Library-SpacetimeDBUnityTestsuite- - Library- - - name: Patch com.clockworklabs.spacetimedbsdk dependency in manifest.json working-directory: unity-tests~/client/Packages run: | @@ -145,6 +142,12 @@ jobs: yq e -i '.dependencies["com.clockworklabs.spacetimedbsdk"] = "https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk.git#${{ github.head_ref }}"' manifest.json cat manifest.json + - uses: actions/cache@v3 + with: + path: unity-tests~/client/Library + key: Unity-${{ github.head_ref }} + restore-keys: Unity- + - name: Run Unity tests uses: game-ci/unity-test-runner@v4 with: From cefc727b7693fe97e3dd848fef2bb17bf20c8be6 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 5 Feb 2025 21:48:15 +0000 Subject: [PATCH 169/223] Rewrite C# codegen to the new Lang infra + fixes (#220) ## Description of Changes This is the companion PR for https://github.com/clockworklabs/SpacetimeDB/pull/2184, please see the other PR for full description. On the client side main changes are: - Regenerate .NET and Unity test client bindings and test snapshot. - Remove `IDatabaseRow` since V9 multi-tables splits data types from actual table definitions, so those "table data types" are no longer special. Just using `IStructuralReadWrite` in its place now. - Add base index classes as mentioned in the other PR. - As a sub-improvement, the non-unique index class actually does indexing instead of iterating over the entire table like we did before. - Remove internal-but-not-really `InternalInvokeValueDeleted` and `InternalInvokeValueInserted` methods in favour of private events. ## API - [x] This is an API breaking change to the SDK Removes some technically-visible but internal APIs. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2184 ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: ingvar/csharp-new-codegen ## Testing *Write instructions for a test that you performed for this PR* - [x] Manually tested Blackholio --------- Co-authored-by: James Gilles --- sdks/csharp/.github/workflows/test.yml | 8 +- sdks/csharp/DEVELOP.md | 13 + .../examples~/quickstart/client/README.md | 10 + .../client/module_bindings/Message.cs | 43 ---- .../Reducers/IdentityConnected.g.cs | 37 +++ .../Reducers/IdentityDisconnected.g.cs | 37 +++ .../module_bindings/Reducers/SendMessage.g.cs | 62 +++++ .../module_bindings/Reducers/SetName.g.cs | 62 +++++ .../module_bindings/SpacetimeDBClient.g.cs | 97 ++++++++ .../module_bindings/Tables/Message.g.cs | 27 +++ .../client/module_bindings/Tables/User.g.cs | 39 +++ .../client/module_bindings/Types/Message.g.cs | 39 +++ .../client/module_bindings/Types/User.g.cs | 38 +++ .../quickstart/client/module_bindings/User.cs | 42 ---- .../_Globals/SpacetimeDBClient.cs | 224 ------------------ .../dotnet/cs/SpacetimeDB.BSATN.Codegen.dll | Bin 58368 -> 58368 bytes .../SpacetimeDB.BSATN.Runtime.dll | Bin 66560 -> 66560 bytes sdks/csharp/src/ClientCache.cs | 43 ---- sdks/csharp/src/RemoteTablesBase.cs | 28 +++ ...Cache.cs.meta => RemoteTablesBase.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/BsatnRowList.cs | 39 --- .../SpacetimeDB/ClientApi/BsatnRowList.g.cs | 36 +++ ...RowList.cs.meta => BsatnRowList.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/CallReducer.cs | 47 ---- .../SpacetimeDB/ClientApi/CallReducer.g.cs | 44 ++++ ...lReducer.cs.meta => CallReducer.g.cs.meta} | 0 .../SpacetimeDB/ClientApi/ClientMessage.cs | 20 -- .../SpacetimeDB/ClientApi/ClientMessage.g.cs | 18 ++ ...essage.cs.meta => ClientMessage.g.cs.meta} | 0 .../ClientApi/CompressableQueryUpdate.cs | 18 -- .../ClientApi/CompressableQueryUpdate.g.cs | 16 ++ ...meta => CompressableQueryUpdate.g.cs.meta} | 0 .../SpacetimeDB/ClientApi/DatabaseUpdate.cs | 32 --- .../SpacetimeDB/ClientApi/DatabaseUpdate.g.cs | 29 +++ ...pdate.cs.meta => DatabaseUpdate.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/EnergyQuanta.cs | 31 --- .../SpacetimeDB/ClientApi/EnergyQuanta.g.cs | 28 +++ ...yQuanta.cs.meta => EnergyQuanta.g.cs.meta} | 0 .../SpacetimeDB/ClientApi/IdentityToken.cs | 44 ---- .../SpacetimeDB/ClientApi/IdentityToken.g.cs | 39 +++ ...yToken.cs.meta => IdentityToken.g.cs.meta} | 0 .../ClientApi/InitialSubscription.cs | 42 ---- .../ClientApi/InitialSubscription.g.cs | 39 +++ ....cs.meta => InitialSubscription.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/OneOffQuery.cs | 39 --- .../SpacetimeDB/ClientApi/OneOffQuery.g.cs | 36 +++ ...OffQuery.cs.meta => OneOffQuery.g.cs.meta} | 0 .../ClientApi/OneOffQueryResponse.cs | 47 ---- .../ClientApi/OneOffQueryResponse.g.cs | 44 ++++ ....cs.meta => OneOffQueryResponse.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/OneOffTable.cs | 39 --- .../SpacetimeDB/ClientApi/OneOffTable.g.cs | 36 +++ ...OffTable.cs.meta => OneOffTable.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/QueryId.cs | 31 --- .../src/SpacetimeDB/ClientApi/QueryId.g.cs | 28 +++ .../{QueryId.cs.meta => QueryId.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/QueryUpdate.cs | 39 --- .../SpacetimeDB/ClientApi/QueryUpdate.g.cs | 36 +++ ...ryUpdate.cs.meta => QueryUpdate.g.cs.meta} | 0 .../SpacetimeDB/ClientApi/ReducerCallInfo.cs | 47 ---- .../ClientApi/ReducerCallInfo.g.cs | 44 ++++ ...Info.cs.meta => ReducerCallInfo.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/RowSizeHint.cs | 17 -- .../SpacetimeDB/ClientApi/RowSizeHint.g.cs | 15 ++ ...SizeHint.cs.meta => RowSizeHint.g.cs.meta} | 0 .../SpacetimeDB/ClientApi/ServerMessage.cs | 23 -- .../SpacetimeDB/ClientApi/ServerMessage.g.cs | 21 ++ ...essage.cs.meta => ServerMessage.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/Subscribe.cs | 38 --- .../src/SpacetimeDB/ClientApi/Subscribe.g.cs | 35 +++ ...{Subscribe.cs.meta => Subscribe.g.cs.meta} | 0 .../SpacetimeDB/ClientApi/SubscribeApplied.cs | 47 ---- .../ClientApi/SubscribeApplied.g.cs | 44 ++++ ...ied.cs.meta => SubscribeApplied.g.cs.meta} | 0 .../SpacetimeDB/ClientApi/SubscribeRows.cs | 43 ---- .../SpacetimeDB/ClientApi/SubscribeRows.g.cs | 40 ++++ ...beRows.cs.meta => SubscribeRows.g.cs.meta} | 0 .../SpacetimeDB/ClientApi/SubscribeSingle.cs | 43 ---- .../ClientApi/SubscribeSingle.g.cs | 40 ++++ ...ngle.cs.meta => SubscribeSingle.g.cs.meta} | 0 .../ClientApi/SubscriptionError.cs | 50 ---- .../ClientApi/SubscriptionError.g.cs | 47 ++++ ...or.cs.meta => SubscriptionError.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/TableUpdate.cs | 47 ---- .../SpacetimeDB/ClientApi/TableUpdate.g.cs | 44 ++++ ...leUpdate.cs.meta => TableUpdate.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/Timestamp.cs | 31 --- .../src/SpacetimeDB/ClientApi/Timestamp.g.cs | 28 +++ ...{Timestamp.cs.meta => Timestamp.g.cs.meta} | 0 .../ClientApi/TransactionUpdate.cs | 63 ----- .../ClientApi/TransactionUpdate.g.cs | 58 +++++ ...te.cs.meta => TransactionUpdate.g.cs.meta} | 0 .../ClientApi/TransactionUpdateLight.cs | 38 --- .../ClientApi/TransactionUpdateLight.g.cs | 35 +++ ....meta => TransactionUpdateLight.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/Unsubscribe.cs | 38 --- .../SpacetimeDB/ClientApi/Unsubscribe.g.cs | 35 +++ ...ubscribe.cs.meta => Unsubscribe.g.cs.meta} | 0 .../ClientApi/UnsubscribeApplied.cs | 47 ---- .../ClientApi/UnsubscribeApplied.g.cs | 44 ++++ ...d.cs.meta => UnsubscribeApplied.g.cs.meta} | 0 .../src/SpacetimeDB/ClientApi/UpdateStatus.cs | 18 -- .../SpacetimeDB/ClientApi/UpdateStatus.g.cs | 16 ++ ...eStatus.cs.meta => UpdateStatus.g.cs.meta} | 0 sdks/csharp/src/SpacetimeDBClient.cs | 86 +++---- sdks/csharp/src/Table.cs | 147 ++++++++---- ...p_dumpName=LegacySubscribeAll.verified.txt | 94 ++++---- ...ump_dumpName=SubscribeApplied.verified.txt | 142 +++++------ sdks/csharp/tests~/SnapshotTests.cs | 10 +- sdks/csharp/tools~/gen-client-api.bat | 23 +- sdks/csharp/tools~/gen-client-api.sh | 5 +- sdks/csharp/tools~/gen-quickstart.sh | 9 + sdks/csharp/unity-tests~ | 2 +- 113 files changed, 1763 insertions(+), 1637 deletions(-) create mode 100644 sdks/csharp/examples~/quickstart/client/README.md delete mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Tables/Message.g.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Tables/User.g.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs create mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/Types/User.g.cs delete mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/User.cs delete mode 100644 sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs delete mode 100644 sdks/csharp/src/ClientCache.cs create mode 100644 sdks/csharp/src/RemoteTablesBase.cs rename sdks/csharp/src/{ClientCache.cs.meta => RemoteTablesBase.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{BsatnRowList.cs.meta => BsatnRowList.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{CallReducer.cs.meta => CallReducer.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{ClientMessage.cs.meta => ClientMessage.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{CompressableQueryUpdate.cs.meta => CompressableQueryUpdate.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{DatabaseUpdate.cs.meta => DatabaseUpdate.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{EnergyQuanta.cs.meta => EnergyQuanta.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{IdentityToken.cs.meta => IdentityToken.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{InitialSubscription.cs.meta => InitialSubscription.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{OneOffQuery.cs.meta => OneOffQuery.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{OneOffQueryResponse.cs.meta => OneOffQueryResponse.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{OneOffTable.cs.meta => OneOffTable.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{QueryId.cs.meta => QueryId.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{QueryUpdate.cs.meta => QueryUpdate.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{ReducerCallInfo.cs.meta => ReducerCallInfo.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{RowSizeHint.cs.meta => RowSizeHint.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{ServerMessage.cs.meta => ServerMessage.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{Subscribe.cs.meta => Subscribe.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{SubscribeApplied.cs.meta => SubscribeApplied.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{SubscribeRows.cs.meta => SubscribeRows.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{SubscribeSingle.cs.meta => SubscribeSingle.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{SubscriptionError.cs.meta => SubscriptionError.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{TableUpdate.cs.meta => TableUpdate.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{Timestamp.cs.meta => Timestamp.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{TransactionUpdate.cs.meta => TransactionUpdate.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{TransactionUpdateLight.cs.meta => TransactionUpdateLight.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{Unsubscribe.cs.meta => Unsubscribe.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{UnsubscribeApplied.cs.meta => UnsubscribeApplied.g.cs.meta} (100%) delete mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs create mode 100644 sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.g.cs rename sdks/csharp/src/SpacetimeDB/ClientApi/{UpdateStatus.cs.meta => UpdateStatus.g.cs.meta} (100%) create mode 100755 sdks/csharp/tools~/gen-quickstart.sh diff --git a/sdks/csharp/.github/workflows/test.yml b/sdks/csharp/.github/workflows/test.yml index 46566d41161..8a4b11e9a18 100644 --- a/sdks/csharp/.github/workflows/test.yml +++ b/sdks/csharp/.github/workflows/test.yml @@ -111,7 +111,7 @@ jobs: - name: Check for changes run: | - git diff --exit-code unity-tests~/client/Assets/Scripts/autogen || { + git diff --exit-code unity-tests~/client-unity/Assets/Scripts/autogen || { echo "Error: Bindings are dirty. Please generate bindings again and commit them to this branch." exit 1 } @@ -135,7 +135,7 @@ jobs: bash ./publish.sh - name: Patch com.clockworklabs.spacetimedbsdk dependency in manifest.json - working-directory: unity-tests~/client/Packages + working-directory: unity-tests~/client-unity/Packages run: | # Replace the com.clockworklabs.spacetimedbsdk dependency with the current branch. # TODO: find out why pointing to a local directory doesn't work - is it because Unity CI action uses Docker? @@ -144,7 +144,7 @@ jobs: - uses: actions/cache@v3 with: - path: unity-tests~/client/Library + path: unity-tests~/client-unity/Library key: Unity-${{ github.head_ref }} restore-keys: Unity- @@ -152,7 +152,7 @@ jobs: uses: game-ci/unity-test-runner@v4 with: unityVersion: 2022.3.32f1 # Adjust Unity version to a valid tag - projectPath: unity-tests~/client # Path to the Unity project subdirectory + projectPath: unity-tests~/client-unity # Path to the Unity project subdirectory githubToken: ${{ secrets.GITHUB_TOKEN }} testMode: playmode useHostNetwork: true diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index 2b9ac7d98ae..e6cb9f31e6a 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -4,3 +4,16 @@ To regenerate this namespace, run the `tools~/gen-client-api.sh` or the `tools~/gen-client-api.bat` script. + +## Developing against a local clone of SpacetimeDB +When developing against a local clone of SpacetimeDB, you'll need to ensure that the packages here can find an up-to-date version of the BSATN.Codegen and BSATN.Runtime packages from SpacetimeDB. + +To develop against a local clone of SpacetimeDB at `../SpacetimeDB`, run the following command: + +```sh +dotnet pack ../SpacetimeDB/crates/bindings-csharp/BSATN.Runtime && ./tools~/write-nuget-config.sh ../SpacetimeDB +``` + +This will create a (`.gitignore`d) `nuget.config` file that uses the local build of the package, instead of the package on NuGet. + +You'll need to rerun this command whenever you update `BSATN.Codegen` or `BSATN.Runtime`. diff --git a/sdks/csharp/examples~/quickstart/client/README.md b/sdks/csharp/examples~/quickstart/client/README.md new file mode 100644 index 00000000000..53885f55e46 --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/README.md @@ -0,0 +1,10 @@ +# Quickstart client +See [SpacetimeDB](https://github.com/clockworklabs/SpacetimeDB)/modules/quickstart-chat + +## Regenerating bindings + +To regenerate bindings: clone SpacetimeDB next to this repo, then in the root of this repo: + +```bash +tools~/gen-quickstart.sh ../SpacetimeDB +``` \ No newline at end of file diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs deleted file mode 100644 index c63d4bfada5..00000000000 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/Message.cs +++ /dev/null @@ -1,43 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - [SpacetimeDB.Type] - [DataContract] - public partial class Message : IDatabaseRow - { - [DataMember(Name = "sender")] - public SpacetimeDB.Identity Sender; - [DataMember(Name = "sent")] - public ulong Sent; - [DataMember(Name = "text")] - public string Text; - - public Message( - SpacetimeDB.Identity Sender, - ulong Sent, - string Text - ) - { - this.Sender = Sender; - this.Sent = Sent; - this.Text = Text; - } - - public Message() - { - this.Sender = new(); - this.Text = ""; - } - - } -} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs new file mode 100644 index 00000000000..89ef3a69fdc --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityConnected.g.cs @@ -0,0 +1,37 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void IdentityConnectedHandler(EventContext ctx); + public event IdentityConnectedHandler? OnIdentityConnected; + + public bool InvokeIdentityConnected(EventContext ctx, Reducer.IdentityConnected args) + { + if (OnIdentityConnected == null) return false; + OnIdentityConnected( + ctx + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class IdentityConnected : Reducer, IReducerArgs + { + string IReducerArgs.ReducerName => "identity_connected"; + } + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs new file mode 100644 index 00000000000..8f3d051a2da --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/IdentityDisconnected.g.cs @@ -0,0 +1,37 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void IdentityDisconnectedHandler(EventContext ctx); + public event IdentityDisconnectedHandler? OnIdentityDisconnected; + + public bool InvokeIdentityDisconnected(EventContext ctx, Reducer.IdentityDisconnected args) + { + if (OnIdentityDisconnected == null) return false; + OnIdentityDisconnected( + ctx + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class IdentityDisconnected : Reducer, IReducerArgs + { + string IReducerArgs.ReducerName => "identity_disconnected"; + } + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs new file mode 100644 index 00000000000..974e9a07c78 --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SendMessage.g.cs @@ -0,0 +1,62 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void SendMessageHandler(EventContext ctx, string text); + public event SendMessageHandler? OnSendMessage; + + public void SendMessage(string text) + { + conn.InternalCallReducer(new Reducer.SendMessage(text), this.SetCallReducerFlags.SendMessageFlags); + } + + public bool InvokeSendMessage(EventContext ctx, Reducer.SendMessage args) + { + if (OnSendMessage == null) return false; + OnSendMessage( + ctx, + args.Text + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SendMessage : Reducer, IReducerArgs + { + [DataMember(Name = "text")] + public string Text; + + public SendMessage(string Text) + { + this.Text = Text; + } + + public SendMessage() + { + this.Text = ""; + } + + string IReducerArgs.ReducerName => "send_message"; + } + } + + public sealed partial class SetReducerFlags + { + internal CallReducerFlags SendMessageFlags; + public void SendMessage(CallReducerFlags flags) => SendMessageFlags = flags; + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs new file mode 100644 index 00000000000..6d7e2356e49 --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Reducers/SetName.g.cs @@ -0,0 +1,62 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void SetNameHandler(EventContext ctx, string name); + public event SetNameHandler? OnSetName; + + public void SetName(string name) + { + conn.InternalCallReducer(new Reducer.SetName(name), this.SetCallReducerFlags.SetNameFlags); + } + + public bool InvokeSetName(EventContext ctx, Reducer.SetName args) + { + if (OnSetName == null) return false; + OnSetName( + ctx, + args.Name + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SetName : Reducer, IReducerArgs + { + [DataMember(Name = "name")] + public string Name; + + public SetName(string Name) + { + this.Name = Name; + } + + public SetName() + { + this.Name = ""; + } + + string IReducerArgs.ReducerName => "set_name"; + } + } + + public sealed partial class SetReducerFlags + { + internal CallReducerFlags SetNameFlags; + public void SetName(CallReducerFlags flags) => SetNameFlags = flags; + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs new file mode 100644 index 00000000000..a6bef070858 --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/SpacetimeDBClient.g.cs @@ -0,0 +1,97 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + internal RemoteReducers(DbConnection conn, SetReducerFlags flags) : base(conn) => SetCallReducerFlags = flags; + internal readonly SetReducerFlags SetCallReducerFlags; + } + + public sealed partial class RemoteTables : RemoteTablesBase + { + public RemoteTables(DbConnection conn) + { + AddTable(Message = new(conn)); + AddTable(User = new(conn)); + } + } + + public sealed partial class SetReducerFlags { } + public sealed class EventContext : IEventContext + { + private readonly DbConnection conn; + public readonly Event Event; + + public RemoteTables Db => conn.Db; + public RemoteReducers Reducers => conn.Reducers; + public SetReducerFlags SetReducerFlags => conn.SetReducerFlags; + + internal EventContext(DbConnection conn, Event reducerEvent) + { + this.conn = conn; + Event = reducerEvent; + } + } + + public abstract partial class Reducer + { + private Reducer() { } + + public sealed class StdbNone : Reducer { } + } + + public sealed class DbConnection : DbConnectionBase + { + public override RemoteTables Db { get; } + public readonly RemoteReducers Reducers; + public readonly SetReducerFlags SetReducerFlags = new(); + + public DbConnection() + { + Db = new(this); + Reducers = new(this, SetReducerFlags); + } + + protected override Reducer ToReducer(TransactionUpdate update) + { + var encodedArgs = update.ReducerCall.Args; + return update.ReducerCall.ReducerName switch + { + "identity_connected" => BSATNHelpers.Decode(encodedArgs), + "identity_disconnected" => BSATNHelpers.Decode(encodedArgs), + "send_message" => BSATNHelpers.Decode(encodedArgs), + "set_name" => BSATNHelpers.Decode(encodedArgs), + "" or "" => new Reducer.StdbNone(), + var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; + } + + protected override IEventContext ToEventContext(Event reducerEvent) => + new EventContext(this, reducerEvent); + + protected override bool Dispatch(IEventContext context, Reducer reducer) + { + var eventContext = (EventContext)context; + return reducer switch + { + Reducer.IdentityConnected args => Reducers.InvokeIdentityConnected(eventContext, args), + Reducer.IdentityDisconnected args => Reducers.InvokeIdentityDisconnected(eventContext, args), + Reducer.SendMessage args => Reducers.InvokeSendMessage(eventContext, args), + Reducer.SetName args => Reducers.InvokeSetName(eventContext, args), + Reducer.StdbNone => true, + _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; + } + + public SubscriptionBuilder SubscriptionBuilder() => new(this); + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Tables/Message.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Tables/Message.g.cs new file mode 100644 index 00000000000..a0f160c8578 --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Tables/Message.g.cs @@ -0,0 +1,27 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class MessageHandle : RemoteTableHandle + { + protected override string RemoteTableName => "message"; + + internal MessageHandle(DbConnection conn) : base(conn) + { + } + } + + public readonly MessageHandle Message; + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Tables/User.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Tables/User.g.cs new file mode 100644 index 00000000000..eed7485e116 --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Tables/User.g.cs @@ -0,0 +1,39 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class UserHandle : RemoteTableHandle + { + protected override string RemoteTableName => "user"; + + public sealed class IdentityUniqueIndex : UniqueIndexBase + { + protected override SpacetimeDB.Identity GetKey(User row) => row.Identity; + + public IdentityUniqueIndex(UserHandle table) : base(table) { } + } + + public readonly IdentityUniqueIndex Identity; + + internal UserHandle(DbConnection conn) : base(conn) + { + Identity = new(this); + } + + protected override object GetPrimaryKey(User row) => row.Identity; + } + + public readonly UserHandle User; + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs new file mode 100644 index 00000000000..164328ac107 --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Types/Message.g.cs @@ -0,0 +1,39 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Message + { + [DataMember(Name = "sender")] + public SpacetimeDB.Identity Sender; + [DataMember(Name = "sent")] + public ulong Sent; + [DataMember(Name = "text")] + public string Text; + + public Message( + SpacetimeDB.Identity Sender, + ulong Sent, + string Text + ) + { + this.Sender = Sender; + this.Sent = Sent; + this.Text = Text; + } + + public Message() + { + this.Text = ""; + } + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/Types/User.g.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/Types/User.g.cs new file mode 100644 index 00000000000..134f3332fd2 --- /dev/null +++ b/sdks/csharp/examples~/quickstart/client/module_bindings/Types/User.g.cs @@ -0,0 +1,38 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class User + { + [DataMember(Name = "identity")] + public SpacetimeDB.Identity Identity; + [DataMember(Name = "name")] + public string? Name; + [DataMember(Name = "online")] + public bool Online; + + public User( + SpacetimeDB.Identity Identity, + string? Name, + bool Online + ) + { + this.Identity = Identity; + this.Name = Name; + this.Online = Online; + } + + public User() + { + } + } +} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs deleted file mode 100644 index 2d4c79b073e..00000000000 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/User.cs +++ /dev/null @@ -1,42 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - [SpacetimeDB.Type] - [DataContract] - public partial class User : IDatabaseRow - { - [DataMember(Name = "identity")] - public SpacetimeDB.Identity Identity; - [DataMember(Name = "name")] - public string? Name; - [DataMember(Name = "online")] - public bool Online; - - public User( - SpacetimeDB.Identity Identity, - string? Name, - bool Online - ) - { - this.Identity = Identity; - this.Name = Name; - this.Online = Online; - } - - public User() - { - this.Identity = new(); - } - - } -} diff --git a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs deleted file mode 100644 index 031c02f02d2..00000000000 --- a/sdks/csharp/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs +++ /dev/null @@ -1,224 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed class RemoteTables - { - public class MessageHandle : RemoteTableHandle - { - internal MessageHandle() - { - } - - } - - public readonly MessageHandle Message = new(); - - public class UserHandle : RemoteTableHandle - { - - public override void InternalInvokeValueInserted(IDatabaseRow row) - { - var value = (User)row; - Identity.Cache[value.Identity] = value; - } - - public override void InternalInvokeValueDeleted(IDatabaseRow row) - { - Identity.Cache.Remove(((User)row).Identity); - } - - public class IdentityUniqueIndex - { - internal readonly Dictionary Cache = new(16); - public User? Find(SpacetimeDB.Identity value) - { - Cache.TryGetValue(value, out var r); - return r; - } - - } - - public IdentityUniqueIndex Identity = new(); - - internal UserHandle() - { - } - public override object GetPrimaryKey(IDatabaseRow row) => ((User)row).Identity; - - } - - public readonly UserHandle User = new(); - - } - - public sealed class RemoteReducers : RemoteBase - { - internal RemoteReducers(DbConnection conn, SetReducerFlags SetReducerFlags) : base(conn) { this.SetCallReducerFlags = SetReducerFlags; } - internal readonly SetReducerFlags SetCallReducerFlags; - public delegate void SendMessageHandler(EventContext ctx, string text); - public event SendMessageHandler? OnSendMessage; - - public void SendMessage(string text) - { - conn.InternalCallReducer(new Reducer.SendMessage(text), this.SetCallReducerFlags.SendMessageFlags); - } - - public bool InvokeSendMessage(EventContext ctx, Reducer.SendMessage args) - { - if (OnSendMessage == null) return false; - OnSendMessage( - ctx, - args.Text - ); - return true; - } - public delegate void SetNameHandler(EventContext ctx, string name); - public event SetNameHandler? OnSetName; - - public void SetName(string name) - { - conn.InternalCallReducer(new Reducer.SetName(name), this.SetCallReducerFlags.SetNameFlags); - } - - public bool InvokeSetName(EventContext ctx, Reducer.SetName args) - { - if (OnSetName == null) return false; - OnSetName( - ctx, - args.Name - ); - return true; - } - } - - public sealed class SetReducerFlags - { - internal SetReducerFlags() { } - internal CallReducerFlags SendMessageFlags; - public void SendMessage(CallReducerFlags flags) { this.SendMessageFlags = flags; } - internal CallReducerFlags SetNameFlags; - public void SetName(CallReducerFlags flags) { this.SetNameFlags = flags; } - } - - public partial record EventContext : DbContext, IEventContext - { - public readonly RemoteReducers Reducers; - public readonly SetReducerFlags SetReducerFlags; - public readonly Event Event; - - internal EventContext(DbConnection conn, Event reducerEvent) : base(conn.Db) - { - Reducers = conn.Reducers; - SetReducerFlags = conn.SetReducerFlags; - Event = reducerEvent; - } - } - - public abstract partial class Reducer - { - private Reducer() { } - - [SpacetimeDB.Type] - [DataContract] - public partial class SendMessage : Reducer, IReducerArgs - { - [DataMember(Name = "text")] - public string Text; - - public SendMessage(string Text) - { - this.Text = Text; - } - - public SendMessage() - { - this.Text = ""; - } - - string IReducerArgs.ReducerName => "send_message"; - } - - [SpacetimeDB.Type] - [DataContract] - public partial class SetName : Reducer, IReducerArgs - { - [DataMember(Name = "name")] - public string Name; - - public SetName(string Name) - { - this.Name = Name; - } - - public SetName() - { - this.Name = ""; - } - - string IReducerArgs.ReducerName => "set_name"; - } - - public class StdbNone : Reducer {} - public class StdbIdentityConnected : Reducer {} - public class StdbIdentityDisconnected : Reducer {} - } - - public class DbConnection : DbConnectionBase - { - public readonly RemoteTables Db = new(); - public readonly RemoteReducers Reducers; - public readonly SetReducerFlags SetReducerFlags; - - public DbConnection() - { - SetReducerFlags = new(); - Reducers = new(this, this.SetReducerFlags); - - clientDB.AddTable("message", Db.Message); - clientDB.AddTable("user", Db.User); - } - - protected override Reducer ToReducer(TransactionUpdate update) - { - var encodedArgs = update.ReducerCall.Args; - return update.ReducerCall.ReducerName switch { - "send_message" => BSATNHelpers.Decode(encodedArgs), - "set_name" => BSATNHelpers.Decode(encodedArgs), - "" => new Reducer.StdbNone(), - "__identity_connected__" => new Reducer.StdbIdentityConnected(), - "__identity_disconnected__" => new Reducer.StdbIdentityDisconnected(), - "" => new Reducer.StdbNone(), - var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") - }; - } - - protected override IEventContext ToEventContext(Event reducerEvent) => - new EventContext(this, reducerEvent); - - protected override bool Dispatch(IEventContext context, Reducer reducer) - { - var eventContext = (EventContext)context; - return reducer switch { - Reducer.SendMessage args => Reducers.InvokeSendMessage(eventContext, args), - Reducer.SetName args => Reducers.InvokeSetName(eventContext, args), - Reducer.StdbNone or - Reducer.StdbIdentityConnected or - Reducer.StdbIdentityDisconnected => true, - _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") - }; - } - - public SubscriptionBuilder SubscriptionBuilder() => new(this); - } -} diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll index 350d2360afa5704eb5115c84adc06b676f072bef..38d8b13aaa984e87a34cc2cd2ea93b6d0a7a0299 100755 GIT binary patch delta 2322 zcmZuz3v5$W82-=gMrXGv+hFb1ZtET`mzHkr+Kw_67)%-9#*mk2#oe_P2BV#Srw|(4 zBseu}Iygj)i3VrDZH_5id;n%55;S507)52esPRG6L}MaqeE#>|wE^Q!?ti}j`=96B zb8grDj;{M1UH`*rpEN%8{q9~18{0j!hHd1G%}8(g4PYfN6=w0ZYz8~UA7EYV8P0^f z^uPcBK>cmB=<1tpI7*p9vkY33AIwY$4s;*GAQB`8dJLEw$`+zRptX`)^77 zHVZn0#2Jdhy6jY$RRlA&G`NeuXXzDw%H?DEMt)CGwP4EQ`-^N|M;?_^`_>7GcPT+^ z1_`?k8?H1cnUjVv|EtK(w#pU7mzi-7c@5Z%x?UH6Irb31lmVLw$GFEjT|BAU%vaeg zcv@wPv|3Eu` zY-bMsEibOPQOFfd^qRyQ$QHkm#5UZ^pS0iGb&6=Qh6vZ@z#w(4$InwtDDb$-{GDRf z>d{(|32X0yy-APZl+xf_r^lX@TIXD*$M;fdt#dy9Oj?$+Ydu;E6>t|esq-4# zsm{yrm^v@QOX@ri^UaFiY^+!3Dm``+h`AXUX60Z%VZCThtxgbMqpiS`M5}C8hCzsV z6yNqKc#c^7fP@g^nPRB)qN0C8B3?rt+iC=Jt59MNw+OfCBu6EdS>(q=WaVy)cHUA) ztwALUbdy9OHuDOHt-M#IO}f}F^+*<=b{Gqjer9}$w>uiUPEF=hPVM`XsRnF?I5v59 z2W%GnO5xQD?)b7Oc^%V=v__P`sVXkeDS@bBGhqwvRInDfM2GK^ro#!6qMw%NI80aD zs@?5B)gU7Unb1(IB-WBSisjp!Edq1%zA6(x?{cvw{*TK}x4>Q*VOyW;tz>Le?yEAg z%wrU$?lPX_FS={!CVk`X5v(OV>ZuoeCH#oT&6dbtdmdzt_L9jfk2?qnqLaat#0L7- z^v38Ci}UE>iStQd58vzE$9lQnw;=PGRL}=}htJP?_-np9*#VyKuV;t(9sXOC56Y0= z#v1rpzp3zC(%nv<73DjY{CfPrS&d0BSY>m~a-m=rZ9w^|6;QtuU@D#S@$Ekl0eb@xa_1#UW+t{(@{T zANaUNVYdUg;;;qUpc6u{fxJYx4*r^%1n(a-aogbP!mAv* zcWHSQna%qK<1Cy1GkA!F_@SZx5`|6tr`ZH}Qp-6vT)^)cUYD*#pBsLtNXCz&qU7Tm-a9WB1@N?)ocj~<=M*q!{1 zV-8Ax=~%h8TsiCbG?oi+rfpM`G^U?_Xppt+S+f02+5P&N0?|`l?e}{Ee#ztY1X?2j zDOBwZd!Q**YE{ugE>m$)%taW4X)<}CqibsOcNN2oLiiRZ& zS68~P%vGrc@oUHPT$4RqO7@`iz4H9>JvA_|>ApSGZSrq~H;tR=e~yjgPX73K zvwZER>(Z8apqhrCh6e&9C7Qh|Zl#wKAU#BOFNEolh*3DjI|Q?d34xEs-DGhSKL@<> T@y{EXaAJ;}^W~3hw_E=&9BoL@ delta 2219 zcmZ8j4Qx}_6~6bG#NmaMB#^}MPyTIQ;yTZE?8FWfnvj*BH4y$vyD?hFe!&J~d&dc^ zxHM^@De6LjofM%8RV-UsQc8btwS}geQWZg0=qe_yt4L{Sv{f2n>QsrXo3x+vo?|bY zpYFNe`R+OAo_pW9_j%}j-O&5G<3|>pdGYRr6C-AR^2Ee;-hrGi%Uk*lV_UISxECMc z%lK)0iVyMuniw%{XoH$f~186#Cv}j1{DQz}NzKvXCX>pOINXYCq|wqY;|TS`OE+ z-rUX~z@6rH&;L&eR~NB_kh)42B|nAdYktlrF;v@KeuqpXD`R%sVlMrS zrWQ*XOyZT=ZeE9Fbq?NxtLu8mWwfrHzl0yv{bKO;QkGbf=NqAY1VfpIhg96DVf%iF zW` zR|QKH6i8FVOLdgBJr9l$Rb(%L>GZmW`-IZlqzcjs8cW_s;s88^r)&d*!vdl5J>LHpn-rcCsEi3B;Y8iT9SkX2N>O zlv|x3P107tVWKs5QGqDLU8-#~AAUqEoFpN{u}})uo>uj763JGwIM6DXdWC9J=rQ48 zU7)EM{$NTUlYrNMO%`gsk=v=5Vs}Y9gYIn?PhO;WK9q^`EOZGTkp6B@6d5&(2nvaPBnxRw08OQZH z7$!{zFOrnJw8W+hbhK+SXM0j}%4Bg_!<7`k2wz:EFTggX{|Uar9F4hI+U-wqo$ zqpexto}Y{~bG|!$RIcEK`>N))8J@(~ovn0~zH|-?A6H?_)g|1n!na)Xn$mxCJ;R&o zs^^Y2_y`G-owNK@m@b=LHZe=bMHNyB-Y4kSc=*~CgPQsy~QGFBI%ijN%I9~eMclhI2JsvBYAK{SdEYd?G z1~i=$@!I$XG*7%iABYbpj#sFO%ugl7Tw0Q^ovXwbUfD_epd!b(NWLL_>YQQmf1@9q zv-}*7z4{NbJbu1xp}L?H^Ra{Y>Uj$n)4w@i#PQ~9>(h;|FBAErxapz+_gq|4vbd2g zpT7gE@!M}#6-8K#9)$s|X?gnVi^ZI8N8MBt%2Ra|?4hZpym-`M`BP*4rHsz5SaUM>X%TXuLv{#of^Jyqkhnw-*Py5`GfUue)Zh;yFVRW zu3E|A_+CYhDuIx^KMs53U^E`wqap`^Kr|eZwFVr($i6_oA}0oVqmiH- z1X7Z6ZzL9q#C9be!DKi93AuAi$JPzatK%VMmlBiXy}RYj3QdqKQRJA?pX?9BLIDW5 zo1HT5IcmgJGllNC%#7L0)b-sAZyRtw-gE5guP0_Bw1({Okcw+g)Rxm90i3bpFK0I4 ztr;nO&!;;VY;-d}YoWqYSg$7gNDs0Q>tk)C_tJ}XlHSMM%u9vhC)Q8AYSl_30rGW| aubX-od3n-Px4OA-%AYQo{feJ(>i+|@h(-PY diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc4/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll index 6931d32d59672a852cae7cebb511640f2bd7efbc..a6fb2cb90e414871a067498541c4d4bd74a47d87 100755 GIT binary patch delta 432 zcmZqZU}@-Jnb5&q{aOma?sa&~!sQFcslL1J=hNoH=Ui&IQ;QDRAIaZFNXUP@+Oda-VDaYkZM zL5x$dV~C$#P-z}WSxkOXR!mT8PHJLtYD`{gNpVSHUP@w7ijkgS%;X7|q-+aPk{E(L z9F0uP7@(H#R)$&*bZG6R8L{&!9#saueqpFz1au}0^nln36BWf6>n2b8rM>ykFCWIq z4}Pg^=KG_@;%~@c1catQXvkmzBol$OF_@jikO~w@WJm_e8#AN;aUxIzBnDEQ%wP@_ kNoFts!Ze_a0Z`nM!FX#kV=E)m0*mc}OpNatCmOH=0Objd1^@s6 delta 457 zcmZqZU}@-Jnb5&v`sPc|#2y*OLlakqGv-caWUOaAF}V>)F5Jw>#C}g;?aTw~PG!vV zZ#{JA!R()joSP*cXozYUSsEv%CMBk(Sth5XnI|S$7$m0|nHpM}TPCJini(V-8>Jc< z8>X0S&iHzVnRi7&#!3c8-vA~C28KwN#|dwSEV zR{30F1gg=`$j?pH&q+;8(J#+0%GOWL$xqG(v2=lq#GH&2{osPccgHiEj${yNlUAYWWw8kcFaZKmkXZHH$~ z1^NL7)`Qpz6BWf67fvqzrM-FXFJH#Ze1Ftf{EZka8H^bc8B!UNz+@VbpUjZLkj7vR zv$Fc<*&X$(dTrVNHaIddRR1oABz%z!e9K)psly+%OV5U9&!YcpdjBhwL!?Sf2< K?-?f=umb> tables = new(); - - public ClientCache(IDbConnection conn) => this.conn = conn; - - public void AddTable(string name, IRemoteTableHandle table) - where Row : IDatabaseRow, new() - { - if (!tables.TryAdd(name, table)) - { - Log.Error($"Table with name already exists: {name}"); - } - - table.Initialize(name, conn); - } - - internal IRemoteTableHandle? GetTable(string name) - { - if (tables.TryGetValue(name, out var table)) - { - return table; - } - - Log.Error($"We don't know that this table is: {name}"); - return null; - } - - internal IEnumerable GetTables() => tables.Values; - } -} diff --git a/sdks/csharp/src/RemoteTablesBase.cs b/sdks/csharp/src/RemoteTablesBase.cs new file mode 100644 index 00000000000..43b68dcd4ed --- /dev/null +++ b/sdks/csharp/src/RemoteTablesBase.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Linq; + +namespace SpacetimeDB +{ + public abstract class RemoteTablesBase + { + private readonly Dictionary tables = new(); + + protected void AddTable(IRemoteTableHandle table) + { + tables.Add(table.RemoteTableName, table); + } + + internal IRemoteTableHandle? GetTable(string name) + { + if (tables.TryGetValue(name, out var table)) + { + return table; + } + + Log.Error($"We don't know that this table is: {name}"); + return null; + } + + internal IEnumerable GetTables() => tables.Values; + } +} diff --git a/sdks/csharp/src/ClientCache.cs.meta b/sdks/csharp/src/RemoteTablesBase.cs.meta similarity index 100% rename from sdks/csharp/src/ClientCache.cs.meta rename to sdks/csharp/src/RemoteTablesBase.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs deleted file mode 100644 index f284ff71a63..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs +++ /dev/null @@ -1,39 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class BsatnRowList - { - [DataMember(Name = "size_hint")] - public SpacetimeDB.ClientApi.RowSizeHint SizeHint; - [DataMember(Name = "rows_data")] - public System.Collections.Generic.List RowsData; - - public BsatnRowList( - SpacetimeDB.ClientApi.RowSizeHint SizeHint, - System.Collections.Generic.List RowsData - ) - { - this.SizeHint = SizeHint; - this.RowsData = RowsData; - } - - public BsatnRowList() - { - this.SizeHint = null!; - this.RowsData = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.g.cs new file mode 100644 index 00000000000..762281d2dea --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.g.cs @@ -0,0 +1,36 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class BsatnRowList + { + [DataMember(Name = "size_hint")] + public RowSizeHint SizeHint; + [DataMember(Name = "rows_data")] + public System.Collections.Generic.List RowsData; + + public BsatnRowList( + RowSizeHint SizeHint, + System.Collections.Generic.List RowsData + ) + { + this.SizeHint = SizeHint; + this.RowsData = RowsData; + } + + public BsatnRowList() + { + this.SizeHint = null!; + this.RowsData = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/BsatnRowList.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs deleted file mode 100644 index e2ffc881b7a..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs +++ /dev/null @@ -1,47 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class CallReducer - { - [DataMember(Name = "reducer")] - public string Reducer; - [DataMember(Name = "args")] - public System.Collections.Generic.List Args; - [DataMember(Name = "request_id")] - public uint RequestId; - [DataMember(Name = "flags")] - public byte Flags; - - public CallReducer( - string Reducer, - System.Collections.Generic.List Args, - uint RequestId, - byte Flags - ) - { - this.Reducer = Reducer; - this.Args = Args; - this.RequestId = RequestId; - this.Flags = Flags; - } - - public CallReducer() - { - this.Reducer = ""; - this.Args = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.g.cs new file mode 100644 index 00000000000..6757bf31dd3 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.g.cs @@ -0,0 +1,44 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CallReducer + { + [DataMember(Name = "reducer")] + public string Reducer; + [DataMember(Name = "args")] + public System.Collections.Generic.List Args; + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "flags")] + public byte Flags; + + public CallReducer( + string Reducer, + System.Collections.Generic.List Args, + uint RequestId, + byte Flags + ) + { + this.Reducer = Reducer; + this.Args = Args; + this.RequestId = RequestId; + this.Flags = Flags; + } + + public CallReducer() + { + this.Reducer = ""; + this.Args = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/CallReducer.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs deleted file mode 100644 index d35135f95c4..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs +++ /dev/null @@ -1,20 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - public partial record ClientMessage : SpacetimeDB.TaggedEnum<( - SpacetimeDB.ClientApi.CallReducer CallReducer, - SpacetimeDB.ClientApi.Subscribe Subscribe, - SpacetimeDB.ClientApi.OneOffQuery OneOffQuery, - SpacetimeDB.ClientApi.SubscribeSingle SubscribeSingle, - SpacetimeDB.ClientApi.Unsubscribe Unsubscribe - )>; -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs new file mode 100644 index 00000000000..c9646b85605 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs @@ -0,0 +1,18 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record ClientMessage : SpacetimeDB.TaggedEnum<( + CallReducer CallReducer, + Subscribe Subscribe, + OneOffQuery OneOffQuery, + SubscribeSingle SubscribeSingle, + Unsubscribe Unsubscribe + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/ClientMessage.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs deleted file mode 100644 index 0fc85f50a49..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs +++ /dev/null @@ -1,18 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - public partial record CompressableQueryUpdate : SpacetimeDB.TaggedEnum<( - SpacetimeDB.ClientApi.QueryUpdate Uncompressed, - System.Collections.Generic.List Brotli, - System.Collections.Generic.List Gzip - )>; -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.g.cs new file mode 100644 index 00000000000..5fa8e84439c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.g.cs @@ -0,0 +1,16 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record CompressableQueryUpdate : SpacetimeDB.TaggedEnum<( + QueryUpdate Uncompressed, + System.Collections.Generic.List Brotli, + System.Collections.Generic.List Gzip + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs deleted file mode 100644 index 7b28c94be99..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs +++ /dev/null @@ -1,32 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class DatabaseUpdate - { - [DataMember(Name = "tables")] - public System.Collections.Generic.List Tables; - - public DatabaseUpdate(System.Collections.Generic.List Tables) - { - this.Tables = Tables; - } - - public DatabaseUpdate() - { - this.Tables = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.g.cs new file mode 100644 index 00000000000..0313b90c124 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.g.cs @@ -0,0 +1,29 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class DatabaseUpdate + { + [DataMember(Name = "tables")] + public System.Collections.Generic.List Tables; + + public DatabaseUpdate(System.Collections.Generic.List Tables) + { + this.Tables = Tables; + } + + public DatabaseUpdate() + { + this.Tables = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/DatabaseUpdate.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs deleted file mode 100644 index e38a46b5bbc..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs +++ /dev/null @@ -1,31 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class EnergyQuanta - { - [DataMember(Name = "quanta")] - public U128 Quanta; - - public EnergyQuanta(U128 Quanta) - { - this.Quanta = Quanta; - } - - public EnergyQuanta() - { - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.g.cs new file mode 100644 index 00000000000..70942468f70 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.g.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class EnergyQuanta + { + [DataMember(Name = "quanta")] + public U128 Quanta; + + public EnergyQuanta(U128 Quanta) + { + this.Quanta = Quanta; + } + + public EnergyQuanta() + { + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/EnergyQuanta.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs deleted file mode 100644 index 751fcd75153..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs +++ /dev/null @@ -1,44 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class IdentityToken - { - [DataMember(Name = "identity")] - public SpacetimeDB.Identity Identity; - [DataMember(Name = "token")] - public string Token; - [DataMember(Name = "address")] - public SpacetimeDB.Address Address; - - public IdentityToken( - SpacetimeDB.Identity Identity, - string Token, - SpacetimeDB.Address Address - ) - { - this.Identity = Identity; - this.Token = Token; - this.Address = Address; - } - - public IdentityToken() - { - this.Identity = new(); - this.Token = ""; - this.Address = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs new file mode 100644 index 00000000000..56aec6a1053 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs @@ -0,0 +1,39 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class IdentityToken + { + [DataMember(Name = "identity")] + public SpacetimeDB.Identity Identity; + [DataMember(Name = "token")] + public string Token; + [DataMember(Name = "address")] + public SpacetimeDB.Address Address; + + public IdentityToken( + SpacetimeDB.Identity Identity, + string Token, + SpacetimeDB.Address Address + ) + { + this.Identity = Identity; + this.Token = Token; + this.Address = Address; + } + + public IdentityToken() + { + this.Token = ""; + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/IdentityToken.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs deleted file mode 100644 index c614410137a..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs +++ /dev/null @@ -1,42 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class InitialSubscription - { - [DataMember(Name = "database_update")] - public SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate; - [DataMember(Name = "request_id")] - public uint RequestId; - [DataMember(Name = "total_host_execution_duration_micros")] - public ulong TotalHostExecutionDurationMicros; - - public InitialSubscription( - SpacetimeDB.ClientApi.DatabaseUpdate DatabaseUpdate, - uint RequestId, - ulong TotalHostExecutionDurationMicros - ) - { - this.DatabaseUpdate = DatabaseUpdate; - this.RequestId = RequestId; - this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; - } - - public InitialSubscription() - { - this.DatabaseUpdate = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs new file mode 100644 index 00000000000..4a00d705735 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs @@ -0,0 +1,39 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InitialSubscription + { + [DataMember(Name = "database_update")] + public DatabaseUpdate DatabaseUpdate; + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + + public InitialSubscription( + DatabaseUpdate DatabaseUpdate, + uint RequestId, + ulong TotalHostExecutionDurationMicros + ) + { + this.DatabaseUpdate = DatabaseUpdate; + this.RequestId = RequestId; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + } + + public InitialSubscription() + { + this.DatabaseUpdate = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/InitialSubscription.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs deleted file mode 100644 index 58766dedad8..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs +++ /dev/null @@ -1,39 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class OneOffQuery - { - [DataMember(Name = "message_id")] - public System.Collections.Generic.List MessageId; - [DataMember(Name = "query_string")] - public string QueryString; - - public OneOffQuery( - System.Collections.Generic.List MessageId, - string QueryString - ) - { - this.MessageId = MessageId; - this.QueryString = QueryString; - } - - public OneOffQuery() - { - this.MessageId = new(); - this.QueryString = ""; - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.g.cs new file mode 100644 index 00000000000..19c7e90064e --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.g.cs @@ -0,0 +1,36 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class OneOffQuery + { + [DataMember(Name = "message_id")] + public System.Collections.Generic.List MessageId; + [DataMember(Name = "query_string")] + public string QueryString; + + public OneOffQuery( + System.Collections.Generic.List MessageId, + string QueryString + ) + { + this.MessageId = MessageId; + this.QueryString = QueryString; + } + + public OneOffQuery() + { + this.MessageId = new(); + this.QueryString = ""; + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQuery.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs deleted file mode 100644 index a39b3fe1ae7..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs +++ /dev/null @@ -1,47 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class OneOffQueryResponse - { - [DataMember(Name = "message_id")] - public System.Collections.Generic.List MessageId; - [DataMember(Name = "error")] - public string? Error; - [DataMember(Name = "tables")] - public System.Collections.Generic.List Tables; - [DataMember(Name = "total_host_execution_duration_micros")] - public ulong TotalHostExecutionDurationMicros; - - public OneOffQueryResponse( - System.Collections.Generic.List MessageId, - string? Error, - System.Collections.Generic.List Tables, - ulong TotalHostExecutionDurationMicros - ) - { - this.MessageId = MessageId; - this.Error = Error; - this.Tables = Tables; - this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; - } - - public OneOffQueryResponse() - { - this.MessageId = new(); - this.Tables = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs new file mode 100644 index 00000000000..9ec9fd19723 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs @@ -0,0 +1,44 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class OneOffQueryResponse + { + [DataMember(Name = "message_id")] + public System.Collections.Generic.List MessageId; + [DataMember(Name = "error")] + public string? Error; + [DataMember(Name = "tables")] + public System.Collections.Generic.List Tables; + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + + public OneOffQueryResponse( + System.Collections.Generic.List MessageId, + string? Error, + System.Collections.Generic.List Tables, + ulong TotalHostExecutionDurationMicros + ) + { + this.MessageId = MessageId; + this.Error = Error; + this.Tables = Tables; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + } + + public OneOffQueryResponse() + { + this.MessageId = new(); + this.Tables = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/OneOffQueryResponse.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs deleted file mode 100644 index fe667b18ad7..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs +++ /dev/null @@ -1,39 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class OneOffTable - { - [DataMember(Name = "table_name")] - public string TableName; - [DataMember(Name = "rows")] - public SpacetimeDB.ClientApi.BsatnRowList Rows; - - public OneOffTable( - string TableName, - SpacetimeDB.ClientApi.BsatnRowList Rows - ) - { - this.TableName = TableName; - this.Rows = Rows; - } - - public OneOffTable() - { - this.TableName = ""; - this.Rows = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.g.cs new file mode 100644 index 00000000000..36b2a43c3d6 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.g.cs @@ -0,0 +1,36 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class OneOffTable + { + [DataMember(Name = "table_name")] + public string TableName; + [DataMember(Name = "rows")] + public BsatnRowList Rows; + + public OneOffTable( + string TableName, + BsatnRowList Rows + ) + { + this.TableName = TableName; + this.Rows = Rows; + } + + public OneOffTable() + { + this.TableName = ""; + this.Rows = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/OneOffTable.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs deleted file mode 100644 index 07ca5419af6..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs +++ /dev/null @@ -1,31 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class QueryId - { - [DataMember(Name = "id")] - public uint Id; - - public QueryId(uint Id) - { - this.Id = Id; - } - - public QueryId() - { - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs new file mode 100644 index 00000000000..a98c30ede1b --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class QueryId + { + [DataMember(Name = "id")] + public uint Id; + + public QueryId(uint Id) + { + this.Id = Id; + } + + public QueryId() + { + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/QueryId.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs deleted file mode 100644 index 25acc28e7f8..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs +++ /dev/null @@ -1,39 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class QueryUpdate - { - [DataMember(Name = "deletes")] - public SpacetimeDB.ClientApi.BsatnRowList Deletes; - [DataMember(Name = "inserts")] - public SpacetimeDB.ClientApi.BsatnRowList Inserts; - - public QueryUpdate( - SpacetimeDB.ClientApi.BsatnRowList Deletes, - SpacetimeDB.ClientApi.BsatnRowList Inserts - ) - { - this.Deletes = Deletes; - this.Inserts = Inserts; - } - - public QueryUpdate() - { - this.Deletes = new(); - this.Inserts = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.g.cs new file mode 100644 index 00000000000..6921bbd82d8 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.g.cs @@ -0,0 +1,36 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class QueryUpdate + { + [DataMember(Name = "deletes")] + public BsatnRowList Deletes; + [DataMember(Name = "inserts")] + public BsatnRowList Inserts; + + public QueryUpdate( + BsatnRowList Deletes, + BsatnRowList Inserts + ) + { + this.Deletes = Deletes; + this.Inserts = Inserts; + } + + public QueryUpdate() + { + this.Deletes = new(); + this.Inserts = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/QueryUpdate.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs deleted file mode 100644 index ba12f153405..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class ReducerCallInfo - { - [DataMember(Name = "reducer_name")] - public string ReducerName; - [DataMember(Name = "reducer_id")] - public uint ReducerId; - [DataMember(Name = "args")] - public System.Collections.Generic.List Args; - [DataMember(Name = "request_id")] - public uint RequestId; - - public ReducerCallInfo( - string ReducerName, - uint ReducerId, - System.Collections.Generic.List Args, - uint RequestId - ) - { - this.ReducerName = ReducerName; - this.ReducerId = ReducerId; - this.Args = Args; - this.RequestId = RequestId; - } - - public ReducerCallInfo() - { - this.ReducerName = ""; - this.Args = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.g.cs new file mode 100644 index 00000000000..b7b48044a07 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.g.cs @@ -0,0 +1,44 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReducerCallInfo + { + [DataMember(Name = "reducer_name")] + public string ReducerName; + [DataMember(Name = "reducer_id")] + public uint ReducerId; + [DataMember(Name = "args")] + public System.Collections.Generic.List Args; + [DataMember(Name = "request_id")] + public uint RequestId; + + public ReducerCallInfo( + string ReducerName, + uint ReducerId, + System.Collections.Generic.List Args, + uint RequestId + ) + { + this.ReducerName = ReducerName; + this.ReducerId = ReducerId; + this.Args = Args; + this.RequestId = RequestId; + } + + public ReducerCallInfo() + { + this.ReducerName = ""; + this.Args = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/ReducerCallInfo.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs deleted file mode 100644 index 71c04c1b956..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs +++ /dev/null @@ -1,17 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - public partial record RowSizeHint : SpacetimeDB.TaggedEnum<( - ushort FixedSize, - System.Collections.Generic.List RowOffsets - )>; -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.g.cs new file mode 100644 index 00000000000..f3a6c26b36f --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.g.cs @@ -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. + +#nullable enable + +using System; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record RowSizeHint : SpacetimeDB.TaggedEnum<( + ushort FixedSize, + System.Collections.Generic.List RowOffsets + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/RowSizeHint.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs deleted file mode 100644 index bcab7a7670a..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs +++ /dev/null @@ -1,23 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - public partial record ServerMessage : SpacetimeDB.TaggedEnum<( - SpacetimeDB.ClientApi.InitialSubscription InitialSubscription, - SpacetimeDB.ClientApi.TransactionUpdate TransactionUpdate, - SpacetimeDB.ClientApi.TransactionUpdateLight TransactionUpdateLight, - SpacetimeDB.ClientApi.IdentityToken IdentityToken, - SpacetimeDB.ClientApi.OneOffQueryResponse OneOffQueryResponse, - SpacetimeDB.ClientApi.SubscribeApplied SubscribeApplied, - SpacetimeDB.ClientApi.UnsubscribeApplied UnsubscribeApplied, - SpacetimeDB.ClientApi.SubscriptionError SubscriptionError - )>; -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs new file mode 100644 index 00000000000..5e0c12740f7 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs @@ -0,0 +1,21 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record ServerMessage : SpacetimeDB.TaggedEnum<( + InitialSubscription InitialSubscription, + TransactionUpdate TransactionUpdate, + TransactionUpdateLight TransactionUpdateLight, + IdentityToken IdentityToken, + OneOffQueryResponse OneOffQueryResponse, + SubscribeApplied SubscribeApplied, + UnsubscribeApplied UnsubscribeApplied, + SubscriptionError SubscriptionError + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/ServerMessage.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs deleted file mode 100644 index c58f1a46521..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs +++ /dev/null @@ -1,38 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class Subscribe - { - [DataMember(Name = "query_strings")] - public System.Collections.Generic.List QueryStrings; - [DataMember(Name = "request_id")] - public uint RequestId; - - public Subscribe( - System.Collections.Generic.List QueryStrings, - uint RequestId - ) - { - this.QueryStrings = QueryStrings; - this.RequestId = RequestId; - } - - public Subscribe() - { - this.QueryStrings = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.g.cs new file mode 100644 index 00000000000..798ee0f45b4 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.g.cs @@ -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. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Subscribe + { + [DataMember(Name = "query_strings")] + public System.Collections.Generic.List QueryStrings; + [DataMember(Name = "request_id")] + public uint RequestId; + + public Subscribe( + System.Collections.Generic.List QueryStrings, + uint RequestId + ) + { + this.QueryStrings = QueryStrings; + this.RequestId = RequestId; + } + + public Subscribe() + { + this.QueryStrings = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/Subscribe.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs deleted file mode 100644 index 440ef4ca0b1..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs +++ /dev/null @@ -1,47 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class SubscribeApplied - { - [DataMember(Name = "request_id")] - public uint RequestId; - [DataMember(Name = "total_host_execution_duration_micros")] - public ulong TotalHostExecutionDurationMicros; - [DataMember(Name = "query_id")] - public SpacetimeDB.ClientApi.QueryId QueryId; - [DataMember(Name = "rows")] - public SpacetimeDB.ClientApi.SubscribeRows Rows; - - public SubscribeApplied( - uint RequestId, - ulong TotalHostExecutionDurationMicros, - SpacetimeDB.ClientApi.QueryId QueryId, - SpacetimeDB.ClientApi.SubscribeRows Rows - ) - { - this.RequestId = RequestId; - this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; - this.QueryId = QueryId; - this.Rows = Rows; - } - - public SubscribeApplied() - { - this.QueryId = new(); - this.Rows = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs new file mode 100644 index 00000000000..f444322ec04 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs @@ -0,0 +1,44 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SubscribeApplied + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "query_id")] + public QueryId QueryId; + [DataMember(Name = "rows")] + public SubscribeRows Rows; + + public SubscribeApplied( + uint RequestId, + ulong TotalHostExecutionDurationMicros, + QueryId QueryId, + SubscribeRows Rows + ) + { + this.RequestId = RequestId; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.QueryId = QueryId; + this.Rows = Rows; + } + + public SubscribeApplied() + { + this.QueryId = new(); + this.Rows = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeApplied.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs deleted file mode 100644 index dffee90c4ea..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs +++ /dev/null @@ -1,43 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class SubscribeRows - { - [DataMember(Name = "table_id")] - public uint TableId; - [DataMember(Name = "table_name")] - public string TableName; - [DataMember(Name = "table_rows")] - public SpacetimeDB.ClientApi.TableUpdate TableRows; - - public SubscribeRows( - uint TableId, - string TableName, - SpacetimeDB.ClientApi.TableUpdate TableRows - ) - { - this.TableId = TableId; - this.TableName = TableName; - this.TableRows = TableRows; - } - - public SubscribeRows() - { - this.TableName = ""; - this.TableRows = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs new file mode 100644 index 00000000000..590565fde5f --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs @@ -0,0 +1,40 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SubscribeRows + { + [DataMember(Name = "table_id")] + public uint TableId; + [DataMember(Name = "table_name")] + public string TableName; + [DataMember(Name = "table_rows")] + public TableUpdate TableRows; + + public SubscribeRows( + uint TableId, + string TableName, + TableUpdate TableRows + ) + { + this.TableId = TableId; + this.TableName = TableName; + this.TableRows = TableRows; + } + + public SubscribeRows() + { + this.TableName = ""; + this.TableRows = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeRows.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs deleted file mode 100644 index 5df6f3d7a3b..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs +++ /dev/null @@ -1,43 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class SubscribeSingle - { - [DataMember(Name = "query")] - public string Query; - [DataMember(Name = "request_id")] - public uint RequestId; - [DataMember(Name = "query_id")] - public SpacetimeDB.ClientApi.QueryId QueryId; - - public SubscribeSingle( - string Query, - uint RequestId, - SpacetimeDB.ClientApi.QueryId QueryId - ) - { - this.Query = Query; - this.RequestId = RequestId; - this.QueryId = QueryId; - } - - public SubscribeSingle() - { - this.Query = ""; - this.QueryId = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs new file mode 100644 index 00000000000..e4f6f85a871 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs @@ -0,0 +1,40 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SubscribeSingle + { + [DataMember(Name = "query")] + public string Query; + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "query_id")] + public QueryId QueryId; + + public SubscribeSingle( + string Query, + uint RequestId, + QueryId QueryId + ) + { + this.Query = Query; + this.RequestId = RequestId; + this.QueryId = QueryId; + } + + public SubscribeSingle() + { + this.Query = ""; + this.QueryId = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/SubscribeSingle.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs deleted file mode 100644 index 249f8991452..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs +++ /dev/null @@ -1,50 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class SubscriptionError - { - [DataMember(Name = "total_host_execution_duration_micros")] - public ulong TotalHostExecutionDurationMicros; - [DataMember(Name = "request_id")] - public uint? RequestId; - [DataMember(Name = "query_id")] - public uint? QueryId; - [DataMember(Name = "table_id")] - public uint? TableId; - [DataMember(Name = "error")] - public string Error; - - public SubscriptionError( - ulong TotalHostExecutionDurationMicros, - uint? RequestId, - uint? QueryId, - uint? TableId, - string Error - ) - { - this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; - this.RequestId = RequestId; - this.QueryId = QueryId; - this.TableId = TableId; - this.Error = Error; - } - - public SubscriptionError() - { - this.Error = ""; - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs new file mode 100644 index 00000000000..26bbfd9a1c3 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs @@ -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. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SubscriptionError + { + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "request_id")] + public uint? RequestId; + [DataMember(Name = "query_id")] + public uint? QueryId; + [DataMember(Name = "table_id")] + public uint? TableId; + [DataMember(Name = "error")] + public string Error; + + public SubscriptionError( + ulong TotalHostExecutionDurationMicros, + uint? RequestId, + uint? QueryId, + uint? TableId, + string Error + ) + { + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.RequestId = RequestId; + this.QueryId = QueryId; + this.TableId = TableId; + this.Error = Error; + } + + public SubscriptionError() + { + this.Error = ""; + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/SubscriptionError.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs deleted file mode 100644 index d3265065dcd..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs +++ /dev/null @@ -1,47 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class TableUpdate - { - [DataMember(Name = "table_id")] - public uint TableId; - [DataMember(Name = "table_name")] - public string TableName; - [DataMember(Name = "num_rows")] - public ulong NumRows; - [DataMember(Name = "updates")] - public System.Collections.Generic.List Updates; - - public TableUpdate( - uint TableId, - string TableName, - ulong NumRows, - System.Collections.Generic.List Updates - ) - { - this.TableId = TableId; - this.TableName = TableName; - this.NumRows = NumRows; - this.Updates = Updates; - } - - public TableUpdate() - { - this.TableName = ""; - this.Updates = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.g.cs new file mode 100644 index 00000000000..8f8149d5f34 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.g.cs @@ -0,0 +1,44 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class TableUpdate + { + [DataMember(Name = "table_id")] + public uint TableId; + [DataMember(Name = "table_name")] + public string TableName; + [DataMember(Name = "num_rows")] + public ulong NumRows; + [DataMember(Name = "updates")] + public System.Collections.Generic.List Updates; + + public TableUpdate( + uint TableId, + string TableName, + ulong NumRows, + System.Collections.Generic.List Updates + ) + { + this.TableId = TableId; + this.TableName = TableName; + this.NumRows = NumRows; + this.Updates = Updates; + } + + public TableUpdate() + { + this.TableName = ""; + this.Updates = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/TableUpdate.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs deleted file mode 100644 index 27cfa7da95d..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs +++ /dev/null @@ -1,31 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class Timestamp - { - [DataMember(Name = "microseconds")] - public ulong Microseconds; - - public Timestamp(ulong Microseconds) - { - this.Microseconds = Microseconds; - } - - public Timestamp() - { - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs new file mode 100644 index 00000000000..5f5a954d77d --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Timestamp + { + [DataMember(Name = "microseconds")] + public ulong Microseconds; + + public Timestamp(ulong Microseconds) + { + this.Microseconds = Microseconds; + } + + public Timestamp() + { + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/Timestamp.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs deleted file mode 100644 index d2c349ce8d0..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs +++ /dev/null @@ -1,63 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class TransactionUpdate - { - [DataMember(Name = "status")] - public SpacetimeDB.ClientApi.UpdateStatus Status; - [DataMember(Name = "timestamp")] - public SpacetimeDB.ClientApi.Timestamp Timestamp; - [DataMember(Name = "caller_identity")] - public SpacetimeDB.Identity CallerIdentity; - [DataMember(Name = "caller_address")] - public SpacetimeDB.Address CallerAddress; - [DataMember(Name = "reducer_call")] - public SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall; - [DataMember(Name = "energy_quanta_used")] - public SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed; - [DataMember(Name = "host_execution_duration_micros")] - public ulong HostExecutionDurationMicros; - - public TransactionUpdate( - SpacetimeDB.ClientApi.UpdateStatus Status, - SpacetimeDB.ClientApi.Timestamp Timestamp, - SpacetimeDB.Identity CallerIdentity, - SpacetimeDB.Address CallerAddress, - SpacetimeDB.ClientApi.ReducerCallInfo ReducerCall, - SpacetimeDB.ClientApi.EnergyQuanta EnergyQuantaUsed, - ulong HostExecutionDurationMicros - ) - { - this.Status = Status; - this.Timestamp = Timestamp; - this.CallerIdentity = CallerIdentity; - this.CallerAddress = CallerAddress; - this.ReducerCall = ReducerCall; - this.EnergyQuantaUsed = EnergyQuantaUsed; - this.HostExecutionDurationMicros = HostExecutionDurationMicros; - } - - public TransactionUpdate() - { - this.Status = null!; - this.Timestamp = new(); - this.CallerIdentity = new(); - this.CallerAddress = new(); - this.ReducerCall = new(); - this.EnergyQuantaUsed = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs new file mode 100644 index 00000000000..5969357fb6c --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs @@ -0,0 +1,58 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class TransactionUpdate + { + [DataMember(Name = "status")] + public UpdateStatus Status; + [DataMember(Name = "timestamp")] + public Timestamp Timestamp; + [DataMember(Name = "caller_identity")] + public SpacetimeDB.Identity CallerIdentity; + [DataMember(Name = "caller_address")] + public SpacetimeDB.Address CallerAddress; + [DataMember(Name = "reducer_call")] + public ReducerCallInfo ReducerCall; + [DataMember(Name = "energy_quanta_used")] + public EnergyQuanta EnergyQuantaUsed; + [DataMember(Name = "host_execution_duration_micros")] + public ulong HostExecutionDurationMicros; + + public TransactionUpdate( + UpdateStatus Status, + Timestamp Timestamp, + SpacetimeDB.Identity CallerIdentity, + SpacetimeDB.Address CallerAddress, + ReducerCallInfo ReducerCall, + EnergyQuanta EnergyQuantaUsed, + ulong HostExecutionDurationMicros + ) + { + this.Status = Status; + this.Timestamp = Timestamp; + this.CallerIdentity = CallerIdentity; + this.CallerAddress = CallerAddress; + this.ReducerCall = ReducerCall; + this.EnergyQuantaUsed = EnergyQuantaUsed; + this.HostExecutionDurationMicros = HostExecutionDurationMicros; + } + + public TransactionUpdate() + { + this.Status = null!; + this.Timestamp = new(); + this.ReducerCall = new(); + this.EnergyQuantaUsed = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdate.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs deleted file mode 100644 index 3a3ea6b586f..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs +++ /dev/null @@ -1,38 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class TransactionUpdateLight - { - [DataMember(Name = "request_id")] - public uint RequestId; - [DataMember(Name = "update")] - public SpacetimeDB.ClientApi.DatabaseUpdate Update; - - public TransactionUpdateLight( - uint RequestId, - SpacetimeDB.ClientApi.DatabaseUpdate Update - ) - { - this.RequestId = RequestId; - this.Update = Update; - } - - public TransactionUpdateLight() - { - this.Update = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.g.cs new file mode 100644 index 00000000000..9ab88eb3189 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.g.cs @@ -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. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class TransactionUpdateLight + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "update")] + public DatabaseUpdate Update; + + public TransactionUpdateLight( + uint RequestId, + DatabaseUpdate Update + ) + { + this.RequestId = RequestId; + this.Update = Update; + } + + public TransactionUpdateLight() + { + this.Update = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/TransactionUpdateLight.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs deleted file mode 100644 index b6fe8d01c4f..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs +++ /dev/null @@ -1,38 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class Unsubscribe - { - [DataMember(Name = "request_id")] - public uint RequestId; - [DataMember(Name = "query_id")] - public SpacetimeDB.ClientApi.QueryId QueryId; - - public Unsubscribe( - uint RequestId, - SpacetimeDB.ClientApi.QueryId QueryId - ) - { - this.RequestId = RequestId; - this.QueryId = QueryId; - } - - public Unsubscribe() - { - this.QueryId = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs new file mode 100644 index 00000000000..1e652bd2626 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs @@ -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. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Unsubscribe + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "query_id")] + public QueryId QueryId; + + public Unsubscribe( + uint RequestId, + QueryId QueryId + ) + { + this.RequestId = RequestId; + this.QueryId = QueryId; + } + + public Unsubscribe() + { + this.QueryId = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/Unsubscribe.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs deleted file mode 100644 index 26832e7cf87..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs +++ /dev/null @@ -1,47 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - [DataContract] - public partial class UnsubscribeApplied - { - [DataMember(Name = "request_id")] - public uint RequestId; - [DataMember(Name = "total_host_execution_duration_micros")] - public ulong TotalHostExecutionDurationMicros; - [DataMember(Name = "query_id")] - public SpacetimeDB.ClientApi.QueryId QueryId; - [DataMember(Name = "rows")] - public SpacetimeDB.ClientApi.SubscribeRows Rows; - - public UnsubscribeApplied( - uint RequestId, - ulong TotalHostExecutionDurationMicros, - SpacetimeDB.ClientApi.QueryId QueryId, - SpacetimeDB.ClientApi.SubscribeRows Rows - ) - { - this.RequestId = RequestId; - this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; - this.QueryId = QueryId; - this.Rows = Rows; - } - - public UnsubscribeApplied() - { - this.QueryId = new(); - this.Rows = new(); - } - - } -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs new file mode 100644 index 00000000000..c049e227200 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs @@ -0,0 +1,44 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class UnsubscribeApplied + { + [DataMember(Name = "request_id")] + public uint RequestId; + [DataMember(Name = "total_host_execution_duration_micros")] + public ulong TotalHostExecutionDurationMicros; + [DataMember(Name = "query_id")] + public QueryId QueryId; + [DataMember(Name = "rows")] + public SubscribeRows Rows; + + public UnsubscribeApplied( + uint RequestId, + ulong TotalHostExecutionDurationMicros, + QueryId QueryId, + SubscribeRows Rows + ) + { + this.RequestId = RequestId; + this.TotalHostExecutionDurationMicros = TotalHostExecutionDurationMicros; + this.QueryId = QueryId; + this.Rows = Rows; + } + + public UnsubscribeApplied() + { + this.QueryId = new(); + this.Rows = new(); + } + } +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/UnsubscribeApplied.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs deleted file mode 100644 index b788434e96c..00000000000 --- a/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs +++ /dev/null @@ -1,18 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. -// - -#nullable enable - -using System; -using SpacetimeDB; - -namespace SpacetimeDB.ClientApi -{ - [SpacetimeDB.Type] - public partial record UpdateStatus : SpacetimeDB.TaggedEnum<( - SpacetimeDB.ClientApi.DatabaseUpdate Committed, - string Failed, - SpacetimeDB.Unit OutOfEnergy - )>; -} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.g.cs b/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.g.cs new file mode 100644 index 00000000000..1d2c41124d0 --- /dev/null +++ b/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.g.cs @@ -0,0 +1,16 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + public partial record UpdateStatus : SpacetimeDB.TaggedEnum<( + DatabaseUpdate Committed, + string Failed, + SpacetimeDB.Unit OutOfEnergy + )>; +} diff --git a/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs.meta b/sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.g.cs.meta similarity index 100% rename from sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.cs.meta rename to sdks/csharp/src/SpacetimeDB/ClientApi/UpdateStatus.g.cs.meta diff --git a/sdks/csharp/src/SpacetimeDBClient.cs b/sdks/csharp/src/SpacetimeDBClient.cs index 5ca2e938494..2e7bdd3771c 100644 --- a/sdks/csharp/src/SpacetimeDBClient.cs +++ b/sdks/csharp/src/SpacetimeDBClient.cs @@ -14,8 +14,8 @@ namespace SpacetimeDB { - public sealed class DbConnectionBuilder - where DbConnection : DbConnectionBase, new() + public sealed class DbConnectionBuilder + where DbConnection : IDbConnection, new() { readonly DbConnection conn = new(); @@ -45,31 +45,31 @@ public DbConnection Build() return conn; } - public DbConnectionBuilder WithUri(string uri) + public DbConnectionBuilder WithUri(string uri) { this.uri = uri; return this; } - public DbConnectionBuilder WithModuleName(string nameOrAddress) + public DbConnectionBuilder WithModuleName(string nameOrAddress) { this.nameOrAddress = nameOrAddress; return this; } - public DbConnectionBuilder WithToken(string? token) + public DbConnectionBuilder WithToken(string? token) { this.token = token; return this; } - public DbConnectionBuilder WithCompression(Compression compression) + public DbConnectionBuilder WithCompression(Compression compression) { this.compression = compression; return this; } - public DbConnectionBuilder WithLightMode(bool light) + public DbConnectionBuilder WithLightMode(bool light) { this.light = light; return this; @@ -77,51 +77,60 @@ public DbConnectionBuilder WithLightMode(bool light) public delegate void ConnectCallback(DbConnection conn, Identity identity, string token); - public DbConnectionBuilder OnConnect(ConnectCallback cb) + public DbConnectionBuilder OnConnect(ConnectCallback cb) { - conn.onConnect += (identity, token) => cb.Invoke(conn, identity, token); + conn.AddOnConnect((identity, token) => cb(conn, identity, token)); return this; } public delegate void ConnectErrorCallback(Exception e); - public DbConnectionBuilder OnConnectError(ConnectErrorCallback cb) + public DbConnectionBuilder OnConnectError(ConnectErrorCallback cb) { - conn.webSocket.OnConnectError += (e) => cb.Invoke(e); + conn.AddOnConnectError(e => cb(e)); return this; } public delegate void DisconnectCallback(DbConnection conn, Exception? e); - public DbConnectionBuilder OnDisconnect(DisconnectCallback cb) + public DbConnectionBuilder OnDisconnect(DisconnectCallback cb) { - conn.webSocket.OnClose += (e) => cb.Invoke(conn, e); + conn.AddOnDisconnect(e => cb(conn, e)); return this; } } public interface IDbConnection { + internal void Connect(string? token, string uri, string addressOrName, Compression compression, bool light); + + internal void AddOnConnect(Action cb); + internal void AddOnConnectError(WebSocket.ConnectErrorEventHandler cb); + internal void AddOnDisconnect(WebSocket.CloseEventHandler cb); + internal void LegacySubscribe(ISubscriptionHandle handle, string[] querySqls); internal void Subscribe(ISubscriptionHandle handle, string querySql); internal void Unsubscribe(QueryId queryId); void FrameTick(); void Disconnect(); - internal Task RemoteQuery(string query) where T : IDatabaseRow, new(); + internal Task RemoteQuery(string query) where T : IStructuralReadWrite, new(); + void InternalCallReducer(T args, CallReducerFlags flags) + where T : IReducerArgs, new(); } - public abstract class DbConnectionBase : IDbConnection - where DbConnection : DbConnectionBase, new() + public abstract class DbConnectionBase : IDbConnection + where DbConnection : DbConnectionBase, new() + where Tables : RemoteTablesBase { - public static DbConnectionBuilder Builder() => new(); + public static DbConnectionBuilder Builder() => new(); readonly struct DbValue { - public readonly IDatabaseRow value; + public readonly IStructuralReadWrite value; public readonly byte[] bytes; - public DbValue(IDatabaseRow value, byte[] bytes) + public DbValue(IStructuralReadWrite value, byte[] bytes) { this.value = value; this.bytes = bytes; @@ -170,7 +179,7 @@ struct DbOp internal WebSocket webSocket; private bool connectionClosed; - protected readonly ClientCache clientDB; + public abstract Tables Db { get; } protected abstract Reducer ToReducer(TransactionUpdate update); protected abstract IEventContext ToEventContext(Event reducerEvent); @@ -183,8 +192,6 @@ struct DbOp protected DbConnectionBase() { - clientDB = new(this); - var options = new WebSocket.ConnectOptions { //v1.bin.spacetimedb @@ -349,7 +356,7 @@ void PreProcessMessages() foreach (var update in updates.Tables) { var tableName = update.TableName; - var table = clientDB.GetTable(tableName); + var table = Db.GetTable(tableName); if (table == null) { Log.Error($"Unknown table name: {tableName}"); @@ -393,7 +400,7 @@ HashSet GetInsertHashSet(System.Type tableType, int tableSize) ///

    (List, Dictionary>) PreProcessSubscribeApplied(SubscribeApplied subscribeApplied) { - var table = clientDB.GetTable(subscribeApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {subscribeApplied.Rows.TableName}"); + var table = Db.GetTable(subscribeApplied.Rows.TableName) ?? throw new Exception($"Unknown table name: {subscribeApplied.Rows.TableName}"); var dbOps = new List(); HashSet inserts = new(); @@ -440,7 +447,7 @@ void PreProcessInsertOnlyTable(IRemoteTableHandle table, TableUpdate update, Lis ///

    eV3KMc`FmHOd|0OsKTN= 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 RGhX{=eyz~YKmYF}@IPG@lf(c3 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll new file mode 100755 index 0000000000000000000000000000000000000000..399de6b034e49f96a3d6a61eba8ff60d2d33334a GIT binary patch literal 58368 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/analyzers/dotnet/cs/SpacetimeDB.BSATN.Codegen.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll new file mode 100755 index 0000000000000000000000000000000000000000..94c8e2f09b60dd76c2fcbe27f95ebdf5f86741cf GIT binary patch literal 66048 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 literal 0 HcmV?d00001 diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta similarity index 100% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc1-hotfix1/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.dll.meta diff --git a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml similarity index 90% rename from sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml rename to sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml index 1498cec1839..b95737b6a3b 100755 --- a/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc2/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml +++ b/sdks/csharp/packages/spacetimedb.bsatn.runtime/1.0.0-rc3/lib/netstandard2.1/SpacetimeDB.BSATN.Runtime.xml @@ -117,32 +117,11 @@ (This might be wrong if the string is printed after, say, a unicode right-to-left marker. But, well, what can you do.) - - Similar to `Convert.ToHexString`, but that method is not available in .NET Standard - which we need to target for Unity support. - -

    1Wi*Y0fK zqwZ0_-@0>wyWRP~r`!d=r`=~?;7ji5 zz&-96z`gESz?a=~fUmd@1itD%2>6=20{FVS3iyV*2Kc6XKJX*=Lg2^lgMpv87Xd$Y z9}4`JyAJr7yB_$ty8-xxdpYn+cN1`*dlm5C?lr)#+|9uMxDNw^3t2|qQ)t*6Mjpqblt>;AGe9!lQ3p^(S7kW+we#dhf@L}C!Pm^*Log84%Y#l>Uz(^z#BY|0`KrV4!qOzB=8Z>Zs4Pyr-6@oo&i4Y z`91In&-1`1Juf1M-vZIzJbwf}<=I26%kwhu_nud&jd@-JKJR&h+Lh-mYD=ECsV#Z_ zifdm5qUCtr0lwvVm)ei#J@EeoqHTCSptj-p2&iX$4BicNDo@s@!0fEgfZnVxfTObZ zAvOnyc}vz;z>~7R2I6azO!V2T4B#nQnZQ%Cbl|yJ9^j9&vVrGkjRO88D;N0Nto%%e z+6}~S$tr;UG!T6!YYg;ffba>~@wia?CHR} zvS$GA$({wgH+v57zU%{m_h%mj+?!nid?mXI`1kA@;JexLf&a)}2>dYnVBGg3ApCRo zBH$<4hl2SOh(48F2mCy{9?Ta&r^@s;05$J&pzdt~W_wp5)(b=}dDj4Qz0F|qfap!$ z!+=HJ7GSZr4LH@i0XWTjB+^U=VwUSY8aUIt5zH(gX1U&W;C!zSxWMZNF7z6}Mc!_t zSqwyv@CJZ&-d-?Ef$-JdKHxfU7GjP2(3Ow990Nmi+3OvF)i1bGS(J#Cw0FUvW z2xcP?{lfb_;3n_Mz@Yb3V4wFiV90wqJs0nf=(%{$Li!jGV737YG9bnqjW9}i~@4y_c{s881 zmE#!#j`i$tZh#lv1zh480}U0b^i}RNn=2r23g>2zVKoqv20>0e|fo z0zLue7>LxH9>P|2n=+Q&K=fL>YUNC<3AsD~<988y*oxKaV zIC}`#n7zZu}qn-lOqh0_LP=5jwKz|$pehKC{^rl_FE#4vE zN!}gKUiCvTy=n+dueu3LP~8b8s9pjSRIh{SQ-1@~r*cLO0mqKo;S8ywQM-VP!Gu&J zn6O$4Calf|6IK_3=~tJ5=~wG>hJZ)q>~L;Yk(^z?Yrt$)H-m|&$G}9?=-eUT#M~Xu zsH)7}1#AQpRcpcEKf(YLQ)hySsh@xuP&a@XP>+EbP`?ASMg0ZL7Uj$v0%qmyaBfwl zdAop(V798YV794FFx%91V794S!3?TZpPWwOt)kunM@TU=6UNpc&X%a2W8Uf)?QS3)+CE6l?(gpx{X04-1Y4 zo>8z7cxFL6@azH~@Z17F@W%xP@FxY`zzYikz@HWL0)Jl6r!G}b;f|LnRY*9xFbpg# zJQ_H*&<`A6XaFY`ZU#;+i~@@a2Y^!xw*pHG2Z7THPXHcJc%r&O%`Kb{EH7M$kIjBC zt^%Ke-8$}M;O*m11>QOCG~iw1P6ysI?ni2->a^#HP1)Mj2 z2)F>uT*neHa~&OE<~oi8Q{jk!sc>94eh7F8m`cac_+7xK#t#8s08{071x%I0Jz)r# zHv##mD%GUcsZJGCQFVekMV+b6R~M@*)%EIDb+39#y{P`A{-Qph&$t~P$7shyN10=; zquQ~^(dby~*x=aY=y7az9Pc>AahBsk$0d%d9XC7fay;mG!ttzQkK;|p-yI)2{*9^W zDCbybv2%uVo^zqI&biXr;yl{f>Fje3I8Sn(?mW-=bLW-L>z%hd?{_}ze9HNv^Ht|x zoF6zpbE*taMt;V`jIxY58Pyq!G8!`0W^Bl4&*;h6oH3YjO2%0k7i3(LadpNoGw#ZG zFyrxzXEXL>ypi$ujE^(+Wn{R#t}(7Dt^-^Lx#qi;xSCvtxsG!AUA?ZD>qOUSu5(=% zxh{8I=eo^xuj@Ci-LB_dFT4Kide8N#>noR*nVUH-vp92RW<}=0%(~2#nJt+|XZkaP znFE<8W}cRLZstXqmuFs^d28mqnGaS zdTo`~s%_K^Eu?MLzNej`J*&O1{ae%YG5R#UNnV^?c&l=gH10&pJKplB}Du{+6X>kI(*2 zc3pNX`-1ETv)|7CGP}rog7?SX+r7_wKlQpsO&_&tRAAKcqfQ?6+Nifjy*ujTQH42^ za!PaN{v-KsAfidI9o-+2TvA2(XZtOc_KN|b@aUYHQVqC@eOUK_k{_*j@8~^I~ zzmIoJa8DRFVcmpH6CRncd%|-Q_Dpzv!rvx*IN^&4B@<^&teAN4#P*4yi6>5ca^k2- z=TCZi(#w%b*Cr&P#+&H;;@)47Lldqb5)8w6#cTN7?Z75w^x}kJaX`pml>B*%(FTJkxw$fjhK3lq{^yAWuGH=hd zW%Xq(Wyh5DmYq=cgR%?Ct}45!?BTNK%U&sayX=#)ugbjB#!M@kcHp$yX@^ehoOb%O z^QY~YcE_||O?!0Ohtpisr%gX_`m*U~O#kup9n)`}{^;}{Jvk#uVZ1zdBFPnYc?AvGmYWAOJzdu{e**0fr&V6%U zpYzU~$#dt<-8lD>xi`;!c<%diKc74Hz=IB4d|>;5Cm(ppflnSdzI;vjvE|+6_mn?V z{!)3?K~)EBKj@=_s^*2~ZJ&4fyn>2o#pxC2S6o|hf5l@Jzpr?u;;$9|toW+JU71%o zzH(~i%*uI{3o7d>n<@{hJhJkKmD?+CuH04mMCI$1?^OP?Qm^`X)fH8@Roz#$yXwWN zzgK-y<*lAlJ)?SAb$j*Q)sI#`UH$j!r8NUJ7uH--^Ki{SYCf&`PmNxiS39A$w02Hy zb?u_s#@goEnH8EkBg6H5r83kQqaIZA)vwiJ z^^jVkexvHt!wNH4wM;##8r5TJg?b#}34HbOq*|kXtJbRB2v4bI^|V@#FFM-PGwN{l zEW+>A27KLdgnC{bsa{Y=s~6QV>JMt8`Xj#fcuBRZJ!%ua`tYfjRfl>-`PHkcQ~e2F zd%UK))$6K9y@Bwi3aGc#aq7wI6RYCPvgukgi^^OYRE0M5zSM{rZAiSqG!;>Jzn9eTwiewM~77@VOdPUm$#`j#v8-{;f_@U#ah_|EN>d z*9gjSs&Y8aP)>vl$2rP{kcpr<&QrSM$I9)vKzR_d5V8@x2%`{k5ON(qRe6q|seFXd z2n7g*j*HY7gt3n8Y8=9Ngb4@}5hghc#5a~*%dC)V$(a>x7XAcT32PgI5DU#imaxvFw}sj3~> zjv9nog!u>y5EdeQ$1%!ruw$m<5XUTx`EwnM9Tkp49hHtHjw)`XlhqLyI#`}jPj(U6 zB*mTvo8(M&_gIp%Svpj?#LpAHQsf~b7mHjf@^F?eb%fZpj)O0Aur%}e4%sBdKEz?B zTj9X{aot+jB-e>t&vLwKh2;DpIe(Eyi9ANq9V_WJiR=*BDY8pskI3(eyc+i>c`c-a zq?GS^vPp`4BiSUy{w3KY#lD4Xl49RRHc7GXAe*GvJLSH2i@cX*p}J4Xb-(bRI}ZMZ zgJtJ0$R6vwPIs_enn(6{vRS^JPxeIEB&R#geC9e)?<~#xmXl3V?0IC9gzaQ0&zpFX zlCGL;l437*n)SX^(l@YlspTS@M6Qx_Ye-W4Q+Y{B`Hv%;q}V~SNs1jJo21zNWRny- zLN-aUW3Wly=#=Lq@)nV|iM&JPPLX%B%u^K^C?{kUN&H(S@+ud8KTAsIQZKtq{#B8g znWoH#r0b_^rkp_%{|w!f-68`bdqsvtMp+iBDcPo7Eb^;tvz%Xxba+jfAu>~>F47}% zV~#1?MfybgMH(WzMFvFPCh`uEJ4N0t@?Memi+n)jlw4C5i!2dYCUUyS86sziJWOPZ z$TpE1L>?*fXptL5{#4{eA}+vPEQ@$PFTo6nV7BjVxWNEZ=;8l;cDmDzZ-Gm zAjw`MvRUL|kmsrQ^z8_HT?6h%A)iEe8sSCkUF~%p;du@E7pgaFuj^5SKOy`pYsgWP z{fg`Q?7JWh$A{i!&YJ8Mg*DkL5iTp(o43~$9=+Ff0>a4%g9UqC6@`@b{_0J*memMC>lzorui^*NOXG)h|lN~`g z4x!OmP_);z8sV5Cq$_H4{s&=EaZ&d8sYTg43yZQpKzI(pJEkbR8(}3v1?-E)?s4@^ z#cFwKqqDH2(YXO(BZ40xfN%-I4utDUFg}&sgK!tZHI7G1u0yy1;Ukw{0xC!BAgj*4AcU*yV_aWVVNOvF7J%Myj zAl(y4_XN^CfpkwG-4jUnCepo$bZ;WvKBU`+bo-EQAJXkZx_wBu59!8~-Ggu!!ZnVv zvg;6TK)4CvW`tW2Zb!J!u?XoFA>AURTZMG1kZu*ytwOq0NVf{Cb56zR@Ex^s~39HiThblZ_`JJM}Oy6s4}9qG0s-A<(2iF7-WZa32H zM!MZdw;SnpBi(MK+g;Y^)TT8$XCSPYmaA73mgb)@y*B?>(@XPzH~qrgn(Ut;Jd5xg zLT&zg)4x#X955Mr5yI5bFCQ><^cx6&MR*V4;{$T_uMeorpE#p7{~&~AGfvfKOuJY= zbY^LOP4-UxlbLtxk7nJA@PNL4)=s@=)*jahvmPK0*X`6VnYGvT=UK<()MOuv@aAZ` z=hWG6=z-a9>1U5E%|CnWt>AA*SeI9my&mC3SD<8FF7#YVUs3qx=$!~3AUucQ9rNbs zZiJNx%xQfx<<|0<7$|ftGCX(tblk=1^%P!iq(aC^VTA) zLwG>Hr}7K+T;*QZ-pYqOCyX{6Cyd_b(aXO=_!_~HrI%+QWFqWwU0&0YwWp>H!J%?g z20|u+7h#mD1Xijsz_F0y5GG)yHVJYvLJ{<7kkeJEIsjoN!fb@O2;~U#5GoO>5o!=> z5$HcbTmZQUc^-^NJ~>FR#myUgDHuuibpOB4|D_# zL<&{z_s7B!va8L+{`U4|foOlwH&`F^MWY}k`wGdSF|f_(l>94FvVd*RA|+A9yvnqx zz{;IS;~$c^m5`E48oMgRt|6PVV`aG!TkGpH*7*AS1EFq8khTzsi>jmyZBm&`Nn|x^ zErZdR(N|s{4h9W>ED#Pw%bOAg`2NAxFfK%LYtiPX*bB(!j3t73w(KR8w5Y~v(z=aU z`zm8FiuBA#>8qvmD12=-7hd8}G1XEZb;00rBV*KubaARj1fB zWb-XpX^J+50+!O-V36bGa<0`45qN50bOAM*{>Y{@oe|*`00tx`h%cPfM7zUM`*=G@DnGxGL7< zDY7XMP%Ms(nf>~winP8&cySkES^K-N_Wo`u8kK8+guRtvvbiZ8UpWF_m7X7ot{#D} ziSyLmhPA3;t$J9i5e*LoT4TTncGibG4L=N2C5iQDbTldBIJSMA&7t66i?MkCLxcf} zo`cc3IuMPm#kC;h39!nIwbKXhlSD2vjQ;vyIAnk)V(maMC@N;Hef_>j+@hyrki}MW z1kM{BKuAfldB7JFLrRI?&Z+ zM95~_93If5*ZBe*FLi)62y6J~w$KRIMdf3Dg)iCzDkX*demuhNJ|jeC6Fof3lT7}_ zV#7xt9x%2h)z})NFB}=9>wL$P=%`TjEz=HJyr8{3820;u(FzqaQ^&^##XpEFw%7@Y zZu*J1$ydeox=yH)YOvq1vsmYMkrk2**$&XEB zCu$c)2~&%ONpk+l*^@366&P0AOjYXSa9_lT zvOY#;(m#8te%8(Euaf$O(otpp`YP4l4!@5fpWPkJ^0|#;p1-KNnp<{!3M73sZqYqO zmo6fvd6nqwmqewEEqRe4Sy^)uOZ<`;O`$CqA3B%%q6RFQ)`{907A4tp!4%IWW;)LW zHl62^@};5Uo-3Y$b^ZaONlmaJo-2_Wx}-KWNiBwWF8SF>mknQ)e39tlk3?-_)#{HD zzflOu)}cT$-j5Zy`BbVWN*ZLN(9(4@>|NL#GSWLNsO_)Mz4$ME+uA02_O z4;sFREkZKFbR%69Z9Yd$<|01o!q|@R1%lDV zswukGw^juhWrMS+Sv58_tX|f>uC8@OdrQN*y7hIf&FfXG(8Emo`iA8VN2ufMtUnZVp`OMn!E=fMUvD$+XK+1CxDJ3OpL208}C;Gzj@P!BW5;Q4F^8kh!Zj2%3LIx_jlX@KebnYB5=+>{)W{)x&wAetGwS1~C}E?(T@ujmj1~%1=j(KqneO0M8)81U;HA z-#{=XR){VPY$2~9On*2UurORqe!yH6{a7U%=Gc$B;BHhmktD(&4B(at0vBz@E^QLS zwG`i+=81f?F4Rd=YkEvE;8w%e3!TTD=6)WAgQyx>XTohm#p1?*z_07;590y)2Ui4ew9b5#2++A#XYNDV$h1ykz(H(#YM2F`PW|I&VKh0EVxR0^s3x&cl(Fa0-5FR!f zJD#vv(0B{Nste9kz78XT;v>EfLnT}lNcapNmT{5JWk%E=3G~CS)cO5r9u$i` zv+&lsV89neefk?hv>2<47$LH`KS4$@euYTk?gS-KtpR_F*-QBH6pDM8og1`LlHD3K zl>l4``U6qa3`p{mfTX8IB?xQ_govgZASL7rg(2YDI`P2C{rG!m4%SC5DG`w%Vi7nf z3nM)RtE&xx2-R7iFNUWX4g<+GqQB8n4_4G-u|G|i;zbigC~;lP6!N(6Ah(e@2&cJC zej-gCN$)t$&mDSQ#J~iDYtUjxw+6amWN@T)&v(#l&TNa_nWXpm`Wr&A2sFPhf=c04 zEwwB(J?giev=l^*5z3;qt_y9BYRYFWI}Ec6L#3(6%PZ69jVtXDnaQ`C1A{+> z<<@Mc#qHa8i#NB$TAaH*8oqqw9MNR#k)gC?+`-$Uq!p))6ZdbApvp|2JbeuHLK~TI zmZ>r1_(rTLdyIHKdjvbe^ig)dXip=4OlWiiVbZq<;ceAqr^Pp=t0X%sp39a87un9I zcWCx>sV=~lfIPx}qB|{7(wCZ|>o{AL=GC+~Z%Jpa(ZrB#TCwYWAz2F3e3mB2t>zX6 zsfwp``%e-`yxM`ynX;sPadTeCn|3PYjf*m0n45YuViqR8)6%J;Y>CBjTomYjky3c_ zOZ%yS?c|B7Qi8`u;#Y1y?AkXU1!=G@Q&Vyk%`R$GYP6^H3s`w!#2NR;0=Sq zdqv($2l_e^VcA`rgVME3}vCOq4 z4K3XvSiGQ1m|W9q!!g=3ZVUPGduTMKn5O75ql>kzw5*bBTQDPs8bjv~^4pO0XkEl` z0bp$&Ad}5yvJjwBvni&OoNTeBz!rwHqdvhVJv!Fvw)z6Gwoug9Wi+Fy(o!dpK4IfQ znB(3uBZvwo%G_9P*w*7iJ;OGVHgPR)E%DPE;&CbbT1-X6_=Yng-1q!Fk#OkSq~_vV zufWrU*E$?`Bb_DxN*;%4ply!eN0OD?KBUH&r|Z(OYm7*@VWp5$a|Bcn%dDhC5*fmN zn6DeNIye&QDG7dq5e%*hg|~)iEHk6z#>>Ou?x4XtM;!xQ`-!5KmlS=7bq2Gzx4nHS zegj;K#3wm5d*puImp%Eg*Re;53$jO~snHQLwnxxh+RkFSkuEK2CVdP!l=LyE)qec? z!Su1%ox;XRnur#f4v!G!M~-${&KQ8eqfZwfjHHiPmRN(PiRJw~c+mack>5Gm6SVre z)BfbNyg8eO$BFgWBNNLqdaGrR#~LzSi@^&jtkcq#0eyX-PoiuUKT_nd7fRCt;KQ&& zfU`^+&7I3mvslYZQhTI%pla#he&bCiIzrCmGe*2}q(~gV*cyl$@t2n7*$V3$zL78c zUz5l0(t?=(;j(X=oVHI#tN#fgo)%?yp6rd)NkEZerBsO#^#8i!{9W z`?xFnhGgQ>z9AL1Ap2+wX~cARFGXwJwooq(8zZG^!e|pQz9Et9R-}osoVl{anltHd zNFysj?nunRqozy9zKG-Ykj}S|v+lUuZ_Z=b9+)7Du!6W{p5z9-r zj_$`-rHO09!{nm|`$;54N5AgIszqYcKdb#D>FbYKX_@iK zUaDzJ2PH#hjPll2EO{YgGHZ>k(x~|@p3Gv+MwM`Hw9<;l(}@dHY3U90ul6B^t>Ca0 zKk3+nJ#?YE82Pk_c}|7)Q~j+y=+Hf3aI_XpSbgT?86&icvXsRMDY7boD$9$y80mHR zNf3cCXYiqG7Dx0?Juw%}eB0@6ZGcH^qv~5FctOTLb6aCwz#u&skc2$+Q0^k->}!bX52n0l zA)D=hC|GB0A<0jb25o~3xibwpY$GNR4ALHo^>`TFPZV06qYCS`_yRPa!JS*MlT8Us zK^MzQ7T#UpJK`QatT)Tch&5zji<$ZZ?$m-cb!?EywFDso?j7>BjVn_OsYSBbk{>}f z+vbE2r?*-ouw?lwExDX#P*?~>q#C2;yr4HTk(YLSFVTnJtCG!e7F&vvOh{>xC|cqs z$1V@EC7Fp8&kCkBqm=lRST@C6&+i>2XR$5UGGVJNVJ9XXK@e3AA&3<}aA3I) z*<$yR6%&R$pM{YoDy3qIMjuYviK8IlUPCRVH+`Zfc68SAp&=Ry(1&ml zrks{umDr^wQ<47V~!(wo1I-eDenz}jliIKq-#ETm9 zfr!cr3)ZF1MCY>|bcDS%EDZ88HK}+pq~~$3Tmc`Spy)2bAURo7dSPhc17Ysil*hMh z%28{>`&@~kySy>*?bFgjLwbJHEQv6k7@JWx#gwi?w%F2hl9(<6c{zy7MPa5c8pWhI zICvP=Z~R&fF_xw!gcM0K5F;Lgnvs}|^AEh&}QQlX;rj$NReUh={I*7bxbdmE4-Zur_eIk*AWIKWk=>{EPW}g>^6zp6@%Nj7}T~!l^P+7EvXT* z*VWlzJ)FBl=FE#^0;hf;lFQ1yw5a>td`=;ho+JrU5&tSqx7?uH$?Y<;kPW$1c0NdQ@eBETSxs?^kgO2~PK}{t=TQ@V6 zpG+|&g*huvW_StC1&u4M7+pf7iED`sMA(!{N$izNDa~pShs*sMhO{l#q*w-9l8Y>< zh8c_uXkM`-Ms{9RRCNADBBg!COF)u2Ug;)GUQS6SVkL?uW+Jx)5wJv|2PCp#(~=L_ z){K&vur;zi#<_?l8JMbE%Z9isNi3?Q7G08y#bdZi^MRPOFuY@G!~j14f-a<{7Qy+> zSUqOr(twux7<7Cvgf7H7k-R$qOFD`#2(7(~h0LLo zW)9`1D$@hC9;cv4`tgEGCXz6a7v6#K88P9+O7Pl}EVl5u+_27vgOGV_ zn5mPaXf$nF5$Nt|8Hhx}Vy_NwC6i4lMXP~zEM#IViUFjW(Vj6*5+gq@V&QlWl*%2l zxT3v1%Bs9C=2R*^`p4IuburA$ItCEafSs~VOlcELd|@JMr{pMkwHZyFJ||MhMX7X~ zoaUh?W{E+==osk6HW!?78-AiSa#(9aJG5j+n+5?4{PfEQ`ukC)sQ5-n#Z|s^5Hp0; zfnMAFs2sv2)lO?5mP{v4RT6CKV3T~qn0Y=neQa|_G)ymM6O8F`8p(NW4M%zt5iPX2 zhFx}Ajn+d!BMTG9lwng5nyIS4>REUF@&c z#c?L`8TPnx?^H@|pTbEAEG*wsR9QI2-{d4+WiDyuW^9XX{SiVZ3Lr%C-7Q(AM9YZ) zxrta3N1xG399v@Xu7If-qLHTzY%_OS(S(=!gKGjIGos1*K_l-jC*Pj>hTMd0v8}%{ znZ_+emjTRr@S3x+a#Ay?q|{CdojBuNTS?mz)fye2 z(_2|wkdCIgcj_%|RKnv~`M4iS6D3Z<##_6GHBJnB#9Hgu4k?e<^5H{jF|1!XSbw_p zg9mFRjP#|0CDjI;2DO&O^5ugiYBhcNV66(vM-Y}s+4ZzAiIZ(so}H0}VfSXGs7Ue+ zgEi@XK4(a|yOd)kXkwRD7iu6qX%o*<%MY4Cag)FvO zBT(97!2j>z=Joh=drR7TG*P)F{+o_CODfq~j{k)LI=>X>k}1pg{E|wpL^WEOHXCCj zWbYeIGmj~8<9zatxp6DB& zLR0ixvyv$u@QI=6RusEr)+%C4x+)oR9WSrg zjIk72zAvya<^k_yhSmdYi%tEEZL#?SWG2K3nQtwb=@2!MnrF_*1kae6fNy4rB?ZsT ztv`)DAX9MOezYHX;V3VG$QGN=ld~4x?~`P|-Q1<<3`|_N{S}^+t?UFx$BwK#UyZkz zC~m~G!-T2xdcGRZgBRQ+jcxrXm_fSiyOSzDEtwU|V8L$*OgY$r#XVX>AKAQ|VkN$= zwl3|XZ1u`oXjq;`_9;t5gt ztOrH*&``6D)sV>eW(0IJ)r1x7m893rpf4pLN0OKbjDnEEu3PupLdY>-q!q4K$~twJH*b!fk~$X%?h&3&5dK zCFlwjA7ix|Sv#T)#CR6;F<+EVZqRj*pO*AQy zsY*fENH-}l+XuEDC9QQAf^xN!aswMH_p z&Y?oAm&jl1kSpv|Ol0DPJzvP5&+?9?kckttwkUrp!Dsj_l;s_?@YZ|LKBzTEVeHpi zBEn>dA?`zrD2x3p06>4k`i;}=*dJE@)Bdi=CJUiq8{U(|$;N}_>o-b75?lr;2kn$Mv-v&EP2{GUwn z3ACESH$rU2|M(Jl0{#+4j^ndRt&|n+{jAAf!jqXVtMcxK{yq$SPCtm56NWiOp22{$ zI`m{up8PirlV>JLe>}`WOL7~ZIAJPhiEObvT}cy(TC|wF?C6I=RYHf>*k}z8tFgG! zF&JYd`OPhTgoJ^(0to%GX7MCUU-NWV?@Pn zF`E0KQHjm(G-3FnG_E$%-MF1mg~hTK4I{6~ecn~vH8M#b@<|2G(0?&*D zN)ZlFHrpg+{3B4ZD~;GKrLaA5Egn zH^0e5@}Esg@brBcSz^&QWNeE~JJ^;|lPxyyQIjq9aI;I|*ejDQwm+fDf|3lb^*Wlj zORGpajLLt}f+G^|1f-dYK~ISlNz#_`$801|(VCj+4|$k6=92M0yoaO~Ubc3US!~QB zq7k0~CXtvcU~`IIBMV1W8tEROEIE!pZb-!OEYzNs=d{9Fp0W%*AQQ2&W7dpEo<0W7 z)J}4{Mg5z@ZX!Am3b84seACIc_!E0+Q!}T7kxWXZVE?HLOJ`x^xyX-VyECE7AIVy3 z;3O9{Ct>8zW-(!o{P}BwmpI&Hp_hm4 zq#SLs(Ux!ftoIY&lNysa43#z`{2mKW=~6gqS~iY)g^jbGno5Zs{>;U~O3z85xl^Wc zyxEXS;(m6P&s?PxHj;A%qY@ob?kRAX4cTdlHcO6c)cBZSkr@E%Qy1Kf$W+v7#g9tW{dF2N>7eViSe z6RCWM7#|ZCp~r{B#pQgsTZoOL-IBQ>!e}2bnGj-B8YEY$Fv*N&i;HrH<1>>0xhRw4 zE=y!EE6a0)pg$$Tu>T?yw~Zo1^-E)_id1DWSg$&-GFC5={BAdb%{GY;m`5TwT3SaL z4CxCnKB6zi#sPh$o~+JMIA3}}=~bp>)l!|K7{Ca(=-+P~pySBEDCZzZ(^^v+O+1?L zl#okH5bQ=hH#{0Mrxh4IE9@^Cnbc9S6iddk0`!lRcvK75lu)Oo!e&~ICR_o<#;HKF z!fGG3RGov%8hCgF0CZa(z_b+b#%1JA{4iM1V9PkdBgJ+3@2FYbN9^7&+HwvjdmLo zrNw6)dfY2wkteIwz{KbWJ-N6jzns$6&hW>h4}LgOTiy=71(O|S)s zySp=kySux)JA=EsGcdSZ+#LqzGPuj&?(Xhx7iZ_a@9qBHKNa0oCp)V;DykzoGtc1( zz^_`I(3e}OhN#j4upGl5$rzY7kxc#7&bL-TP?xffpctTlYp_9VeNaTl4dS6Th(BQZ z_IRb?*D5+nD@Wnix-X}dmXPvW=RqSRw5&X-yKUm#+$v#7TCV$Kw_0jqn{sBro4tiQ z!PllyS_cZ+ct6{%u!NK-<)>K8VX#y>*nF^D-f`KXI)4%V!;>~xoN6U+^v+z2)_^~f zOFtaB6k6p?hPsH0kg*rfL+f9f#j2KjKX?W4bjd%KjcA3u3=$@|O8E6e-|uGo4?pcf z(7Dn>@FHk=#jMK_Q)pR3+P@z_3l2w?#V{D88ybj!f=u8!N5U-5Om-hQvv$Z~960lF z?L>b>(Y^bU6oZ~wHkrGE#;r781ydcAkEFMevKm!Ma8X<#?8m8(6F;IW2;<&I=4}tX z5H0%SIx~qIGbFK8(=*M#sbL)3rhDvGYppln{H8X-lx%Y@Shqu#yP8p3G2X*d3@B1! zDh4y-9Lh+B!gLdNH0!D4kNn$rioT~-TP3BmLiIxLE~mLahPD{}w^VtJn-=zD4{1Kz zVdCiN7a1TQg3I<6(bzDpKquNxJ~dJ_z8h>whu&mQvwU0)>omo=NV88Y=*cB(dl~_N zDh!u|P2LZ?YPn@ScHzL;_Kfhv|F_06xY9qdW_&K^fnZe0T{a873zd;lO@J;pLAGIO zT^HtqXhy~;k{)3ZALp-b=Bz?OQLXkVl}6>wCBjBb1DwE3%Av1wrt-R&oNP=19_4v$ z>cTpEn;7U2?zR5A_u2fXWM-i?RwQO_8x@bpe2gp|8h8aE)Q0vR<%TAH(v6F5Ok7F0 zTs6!z-q|9)PH)*j6tD#49q-P}l`DeQ$3*>1tZX1T*7cWANBO#ZL)A7)1#ZBPm2Z1k zKb{u@u8zp8IHuSR56qg$r2Su)g%K0w)qi#G$bULM4m3Z|vz?Vna{elcwS>ZQ>jc+< z*(DnJ7ugAE8i+fpN2qS6l&sQELgJ!O`|c#(SKP94g%l2U2;vYq80sX+j21Ow`YO6fL$V8_yb1-G`FpFL>^%CE4pB~z&F53k)F@0?#>Mr# z#FuVSS*M2pl4N&S^l0DsqgXO?a2_dRBwFH_#x3CeVFOuhFy_d$+)BC?>bldLmB&_l z)%byKvY(%0VvUQJ`^H}q^aHI>c8g?q=hrk;D!h6dV2o_8{@|sButQ>g6fItgP?f-2 zjC%0PZ0U z05bJ7%TkUpk+C>EgWOGgldH18%+$-_8BY{t*4GQQVINqCF|*6PwwF^kuXRx7^GVb= zQ;0+rtVFZK)q=IULZT^aMIOz;hg8u-3%g)@o5anl6XN;7 zWEX|=ipJkh-@mnC*3`Z5C>kjr0_}3R`z+vtiFzZvFzXi8O z>LUC8c)>QwCfu456ZPFI31M^6j@q2&z>XU`tbNNM)rlbQ4nbCHI=!rS!MDE|BjWVc z%nL#ZW5-q}@{-HCEumogA%;`U9IcDg|J(bS3;^j_qe>SL&OA0E{=CodbrQbAAmil| z@_MxbuSB3@F7xbF7G?MQZ?oDDzSpENl%1J${b(@G2_{&ZDL_)@zg^!xB8kkFAB=2uJc0!uPLD@x?`VW`$A1VU=r|8xYsLq;yHHK0A z^Gl!~%|_#Hmn?l>n&xtn4`Pe63L!#391tDEl(C+9bMpF7qn4n^Y8e;fEn|$Jw}^Xr zcuF-&dtsP5(rjuK1t&uMuApCaXQnL(x&orj-b>fwpo0-9ICpRV72ip1#l|~iXZf6F z#YT5}(**)yZuD2^@M#GjXHI%GzVnh6fOvw0R7I|8<#e*AzG7snMb$D5=1*=&zh9{X zg{i`lg&BMP!t&W8gVsi8TvKo@ArJLiN`2}6v44na!DC0U%VHYKNhx(mekk^q=JMpJ z*h}?!GOJ^tMw>o*o)02Ewg5)<(I$*#!NjY~juhqpkQfMx%gOtLi4EtMxFYAzUYcUj zu+mNh!J4ut@{$YCt+#}V{f1mTWBbkFaUeU1&6{9nP^rpN zYky1?2>U`f?3ow-gJNh2y^^MSSs@JFy~UC zc~idldpF$>%r}dYtM8I--?Q<%fqjeYp9?b^og1dx|M0SW@32IYyZ(MLX*8h8fL`iR zVt9kJV*BJoF*K`-rg2{&Ssvm~)~#M(;at0%XwVBeIQ%rCJ1Xi-4yq0>#4bA8-E;)w z2$)-;6KXsmki&YI{P~+rZpuoI$hpD@?ns38!34z|TqH~zOph6!PHGVDN#V%ZPJ{0K zi2QO6jukF=<(j9@l2$84&E6QE6V)E{1coJ0Kos^t#~xxbIImdraAs2#EM*M6GJvBW z(BmNU@)xUq0jHipX*OnmvoZ*~+^BhHjn+1m`6*VOk|u>Nsjf_w8{v1a7!KE6iL%TQ z{rpR`G>idLilowb{B8v4Aw8v1JawVMCmSl1a&!1{?3^IgK;)oyhXTB5(Td%{ZyGsM zcxs<&I{YK{xE}f|@yyVQV?E%NQqJ2`>%c4ZzYj&rykBi9uX5Bal<5Xr{BwBwmshUXw;>Z*1JrVh+B^|IE`Kk4j+TT zzep!l?vQT)E<%4%TfMxHhR^x>v^MooJ9o~|QLp9$i2j`<)Fe4D8p1KnYfQ(}dXQ@* z1^{oTwq>5;E~$r&VGN?FE8A?IheOzNAmFQ=u;?ELSpDOL9w|3)A7kv$EDxx|RtA(p8>I>Kus^_Bk$Mop?ikZxH*uZZkZ2y#SkuVi2spo_@E z=2&Ux-LvRyQ782?U~(gzP+>Gc^qNqn1ND^%)J-^b$xxrm`i+8b==yuS4_|*!t}|6& z<+XxG0hV>16;S@xK4B_-LwQ3H#O^hT%KYv+1lx|V{%K|f^m-~VN#>F7F*XneLnTW_qlC_r} z?qFUQ{B2IAyqaC`syzkVg( zeTVWXo^n$9Mt5N-4yO~a&<%-MJ1`%J33Xb6=$d}b?dz&fSJ}m7*10bAqASYNhAfdF zzX7vi*i{ENN_dAH3qHBtLzz)BAotZC)h!~welE_ebn38B5^1$NYD?BY>d=+f`1NxV zZSCZ{*Q%--G^40K+`D^B{`-d8qCIvu=+QL++`~Klu9R4=HdoC*?@YXjRq`D+5xwoA z+qHoORa?pnt-z41uft&~ZA4alct!0Jm;_ZwQirOIH@8c9Jl9L z;hGf$YH7l<8;)SM;9K3j?k`ClX>QeywkKyu(x)gkA9D*B(XHQ(HfwolF8pp^a#57ruVsHQo@TI;&9okTnx<51 znY00%`1!X7&YO-~4W)Nk-!k(WSYLm1wPSL8w}}S9kn9AC(T7rgLLO``1i?*8&eXuQ z6N`G0oj5{m#uRwv`hB5p2mv5Tl>7Y;iEdT^u6pS1Xd-UUVKW9$o6!a9=K_PSfAnX3f6XfW?>2VCAfts6nHoKg={c;VqE z@_}Qp_)Pt|i~YSGX!aZ!+i|x^FsD}-t5IJqxC1*2k=V|q=h=?iAy+1EjsH+@TZwB^ zNnZpXSl-c=6F?eB`kv=nquGOdv)|6IN5n1jYA&N6jtB?2okSNaKT&wTW@O&_suIGi+g%otv0 zZ5@`|CCq{Q3f2iU8qo}G5KNR)JBH4=f2#=*nDMTt+Q3yOIH_{2I8VI`b4%~?Bmi75 zdL%aWN|S+*rE>S8CJA^AatZxbA&0cpKf~W76;y}SrL^r zMYO>{9T6YpH>Af)JEpRmbj5`0txv-xD&e_)cDRyu$+calZqOwy-zGiks@CKk@-TP1 zXZlY_+Uk?=$q4_^WRHGZd$^l?%2D=ZIqR^UB%b2G%1$q2nO-dIm~>;y9`J3AF=K%h ziaeJWl-ob=K%e84J?-4DmDH=EOFO;iQ$}4&PjVI{m@le%ZB1#EBvaE46jJIpR347@ zrCajIyRY?ODmywEGv(+`;=;t<$NeG}{^Uqk)w)tP%a2-$gs6Sjv*xv~mSq>SN`xIN zCfd2G_BF7%s&}~{rk?fuIb>Lm?0T!CUeh9&PI*b^WE|uFB(7AOx?b`-OPu#z%4VQS zK>+8A(Tn)utkLVEyS5-m&g=W9Udf`&^PZ{-wB@v6w;p(!dNjlB18Rgs5!hPYPUB1s<%D-Ryj<`J$&tEV= z!N08iU#Xxj*!2fCP$N_;sXc64+e!Q!#_5LvCof;4op8cx`~$|JL)@rsk+V z`V*ntb}odUqJgHzo!8DxE4mB!ad&je{MN zH6P2NLe5r0IC#0E%V}z6wzq4^ZxVoTXN3FBAHkAoL>L9V1 zm!K8K!X}!-9-)hG?TTkhG!Nep0RGcU7^)J80|B9ccJ75tn+iU}0jOnqB8q#y)zkdwx%^Qm|7y@V3K)?EMHOqdQ@ikb_e* zN^YDbRx`S^-U(-ciLNT(o}QGJzjTvXSj;cqI!b~lX?Hy=J!emv_`Jm+a~m3~*<$=H zV}&UY)tuEhik@Zn)!M5D-|1%+ZC-=V3b2>RrfELfQ*u_F)d{ohi61t0RW+ac^tSDe zW@~2VRs0djK0fM+U_Mu;r}oTf$JSE<_6t!+Xrx&jLsp1-xXgtj(OkX@)2FWYJVK1~ z0B3tYQ=j417Qe@ZU0r539J$Mb^svyxgUb@X7X3Yl=VpdOIZckR+I8xzyD@kvys9zB zH3?aVYeLvFxKf=_$g&m%VUU_};g-;*B0idHI&WrAzGb?eXX2+fD+#B87gp9R{MeIA ziZXjr>Fsh=+X(fyt!-Lzb)m;?RYc{%wLx2OD|%}1e@UF3U#Zb}OnYPT|5N1am46Hi z3~#pS-S{V|4F4>oe^%j#^2|Hsb^C>9fxCfr=+xn`ldcN-_%)@=Nu0CkjI8Z$a^@Jd z$HtTC1=t`1uE1>cV*lgG(iVUWLz?Ma4B1DCw^P`bc!56XiLe80ilKGIC%?JXRWkA0rJ}{U% zb$9r?XwKJE^oH|jvuq=Si#Foo^;Hn&u&wqyzf73>l#aB^VX9Yj4q-|Y5KDrXCk3qe zFJ7*fp~$kGZ-D zJJP}a(ggta0-^la)VspYC%DJfxw1o(D!0vJH^^beam%K8G5c%2=FamrP=z+$rWkqXzyZICd5S z2kz%(Qel>@2kZZ_e%Qxf{^*-!E>SKT*Or|!rY#Q4M8wB zThK&|={%Lm#Z4~m&W`ok`~=4-4pRYj_9SEu$4qk9=~A+xpqpUM+J+-;8Da71oDw(t zCMKvrb&Tdq-?V$u#1a?RgK);DLwO=pRa0_2N@;alaoMb)$i-GlVx2}4SdFX&)Q-7( z$OVA_dg2bvcPATQWmqx#iqFmF;G+#;q|iEwgE?Pf@tCc3Y(6$EKCze5s4lEQ*#Q{f zo>hEY<2hLq_32eM?~^D966wU97@*IT7UW z-cdzZFSik~9I7b-^9;|EdZ^^h?0VIqe1)Y9LvaocD)d;x-spsF+z+3qfjky!A{L}p zt*;g${FjH$$QZa$*76aJd90P$cP#&+$pLhnS0j+I+sOTU_t${&Z9kLLCo1*Nep+yk zjNB#*(PUNYu_Q1e?Y;?2Evt&Nh%0lugv7Tp^LD@iGG2N~?T@859dV#o*FOpn+bMaV zGm6e}tUpvV^XT~`eq$d_`GltHMumZR>u$Rr-y+@Kc3t?&5>Zdz(o;JK-1XWS#-F7h zuk!-VJwKNRMz|BxX~rMT4C55|JHKq5;t$VoM@*!)bH>s(0wmq63+c&@5_`_u%gaaR z8__#e&r6gz1yRzrnPdRgVFCCN;ehhWuxM0my}`xM@}g^KCDNUD@mTsk=5hY+c7Pjs zP`%R_A%a&Ru(Kyh%9Cen|F#?E^+)MXN6cm3)Yn@|nAUJ^+bP&*am7^nkvf~5(h7!@ z)-SF8THHBEE-uKAy^n()u8XH&TBPKTuaDjEz#*0FihSi(4QXCye-UxFFvlvB`h;Hu zB;a{}yS>-_CR@oZy-!I*@Vv^IP z%=29*VuVi;+G}VjWvj($^9us2E<{pTx`*T}GA~ahg0Qz3d{ucWUdFyHVkroWwTbP5 z{W7^zk}SIF9lMfhU)LZEheNPo&`WBbg-( zOink3{T_}qE1lO>nXSyes5&-Frj_T~N$8ft=&8y6^wO`S&$ZI6w>tgb`X^MtjlM5H z#UsmgX%1P7FYmj;E2kU(9OIQ-{_aN2uL0A_)Yk-Fr9u97IO?IVs!wvzJ0idyUfFU z+K4!%Yi!&^sY+Z4dX+D2A-3oR`&BSzW2$7#Q$aM_^9-@)sN=2@H*SVz5+`?DX|T`B z4S=5zc>F+Z`?22QnnSMaOfpx<8R%yHy=@DbvMPn>Mn~3UliyANn#g4KkL3#V5bcyI z^B@x^5$a;MaoM@ws9>x`TQr1oiL=e}3Q(44_qcOjQ~$wrAxFL5w?HMmxbAE#A8_@- zYG|>EU+o%;eE=#!%`37Da^jrZ?7MBtsfL^)pzdw5F>(L<$aF)@M_|S)LVwmi50}3d zLqy2lHa1q=pTqxVUxiW~UdnN9L~+m6K%z$CX$b3c&Qr{-dyjKx4A~MFG=joS(?epf zGSw}}n?9o06a#)g6XX(jPqgYCI5PROR>c#ybgT7WT8caMs0nKJZp z96+eVrS}UpZv_69wCU|E%^GUst@9L29#8cl!L=Tei9Jc#YJ1o$>uPW8f}n zB!u=U8>{MG;2%WyeZ=+e2q`YL#40l_g%lECDR2~-Lb(CAPN7DQZkV9qR<8l3{BP@h zYiEa{L`Kg(aK9x!sFW$1Bk0S|UHH>e3uNYM_ay{-(8BB~g2IF_s=c79+Xi}B<`r*eAbUUGuW7Jj}87F1C8j>77o~1JrHR73dTdyBU2VRzIOW=f2 zzyaGjodQY8DFRsD6!*dt6-!nG50G*e_izQVyrCt!%ekN9b?-NRWP#6^)^eXd|1vWs zD9puxKC|7cl*MEJIi$5zZ*3d%>39D0ALd*h-C-#n2J0+F&^GyA`XqRTcSx8_QQC%l z3CQ6uYv??j{Eo;S4sRORzW;=g%?d=4+3pB%xe+OINeqgOlzDvx$D!A~UWxZ^eB8Zv z-)_P69feXuUf-Z)2zn6RH7&&Ar4O1_Nk6cVN7H}*UhTyrEq&HJY2x<1`h>JNL4u{) zdutU(xHah%{A;>wLJ zT_3SPoB}0W+;t@C4Sm=0b9+B+u|3TLvDiqbgf(my73r1GMjy&4WRE1UV4TaRXt1U1 zJiNeOUZGt(pS;T;W3-f&CrSHcYlDk8JikroT5Y_O;t={>TNULbWGlg)wRlBWDIwzy zvL*CB(FSQ6e(E#&_AmfBF7am%PC9H*M}bd1r~YVv9jH~_8~Ll_NDPvsVPnP5K4gmN z%}qWhe%~9ClRWI6$(b{mE^XpnOlTLM^Lv+RjL%aH4u3Nd;FZudvGGZ98%NfzcEsY( z-z2XQb_-z}M42SUN@pNAVsZ|FrQ3n8u~=I$W)5pl;ZPaO{&9E`R>|-vmjR;vrIJej z(~4gWB?e-9PWtg`w)3DHQ^Z!O6wiF?r479gY}<*~Q=ejqS2dH`L@relQB&n4MaKfm zv@?tq*O5!O#oy0$kxR}4CwU_+8WVn7?Bs+uE(G0vOH~N8^4Ps+TTEV2WGU5;SXZ7m z7i7cmdoC-a1<9@{7lbX(xFWr`Zo>+#?Id#t$Sf-X_pavYiJ_@8Q|&2c%VenedT}|#s6T5)MH>ts{4RR)^+L>7sjnU>9Bqp%zOLgd z!->O}#;S*OFf1dRfBE_Bxly#4JNk@DOwNy3em27FgE!GOo$ndly>>}`=Bbd^=rHX- zPn!H;DG4}Mbt~WHmT3@oxJ_9?<49?Oj_+7losn!*+zP02Ca|VksJ`rDH9-%JGC@yA zj&|;+VIX6=CH07DYs<`!dYMU{9S>z|4aPmK*~JXLOGes2`z;2lf6M5h^6q+$;Cf_m zL&O82cSX)S4F;OR4?~JL8>JIXj3cmmYwj?i&#soR-;dli{X3TgB=P>1L{5b>#97!( zHupikPb5wg5}sOGT^#nhz@7%I2F<8+h8CNK!g1OO7(aJrJp61{1t{cy^QeC0amaKJ zm99E*$r;P$&n=p^o7jM zDA8F)a8gZ5Gdwdw4Q;L(T(5^0)Z7Mwsl{lV-MEvZt-d9@Y1;B?2SKY9+XqZ-gJ1f(OlYcO6!W)R$aQ(t4RU z=>Qh3`TMju2vyQDf#OC4z4ewPoMU~BI9OeQDPsh4K0DLlaSUN&u8{Oe-QV9VjOZKg z9vyiy`_5?@S$hmmKD4CmEw=pju=S>vkIs7BYMkOd0%ds_@*?$=^Q!r*vR88StXQW1 zLh%74h93;B9{q;=LOS(iRW2ai*HMvkS?~@PVjpkXQe3C=7zlQ%+orf z%2#VsW(e3X8jsAAiyhDvTKVOwzG#9tb0Mgt9hXib&7tB_HSa1Xi5=Z5U8Q{^UJx4 z=44vt2@m@O zB4{nrY^n-6T62y9togNW36O^=4}NJ4031>WU%rlzis=@AI%Zglz8*Zssx3?#0F=J- z&X2_rDlzjiZx)LAoU$e=HTW&bb?jwMPOTWZ_K&_vjI%eM$(xWp=>0L3^RUdg67jnV$z*C#NQ!VO_NpY4Th|*>+uk>Ttqr zsv!(7whZj-ZkoHDe`WXUGmZI+Jbb!&xhDu=Pbq9?n}XI;#I<{+Z(|fB;MRKel#(@g zw9Yvic6v<3E79vdFdILAW&DD&Fugu%1`QyKsZEDfoc^Y3@bR)kzt6CS2*TMhOWXK1 zn0!EcnZ@zcCW+u6F=v@C& zvo`JM)Qn#n7-1EY=$#>;S5MDhDUkmJC*E&eX3I!)ogRDa9ZNrCH@KLjWv{dljjNNC zc;zNO8NFt+r9k5Cn>MlhKnDgomRY%^bINGNG)P-|av%|U?^naYtcLb8 z!Fy;=uG$Od`tRYFjT1w>I+fx@zlqI8haszKLo@)p^qAjsKK0=((e$o?8L~BeFK604 z{V<7LyiYiF1n1=*9O)X?Ex#?|ePz5IVoBbPw)of>Yo*-%y}=y8;w_JHK3~0rYsiB4 zDv**@5|43z-y0*7^Ll_lZoZG@P3PA0?c$ht?-~NohW?B#sMIi;rH!@gqOOX)liF0Q z*(x?{4H>H{J!XxmRu0~$)4O^zZjZU}i@nC;X*t?PYRHeMd;@0}`>6r&fJZ1*$M z$@^GorT1l>jd2ma@3p*sn`Ih4Ox9Yea^OhP(vc})w-S46HYVVe6u>anv&rQX;?|lS z$_XQ1syYs^>>OsTLo>VXMYeh@nY6R;@)6Dg;cL{Mcv>0ErtVj8Gu0JkPigBLjmis^ z8kk+gxvwNpb}=`H=Er%*#ShTe!L-&4pVlDiYnDGHT!~0H@z7px( zAJ1J5!3t(Tt24H+#dN+6#!Xg_FR@h_&$+3KTk_o1OYg_(62oz(38i

  • 1Wi*Y0fK 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