diff --git a/Directory.Packages.props b/Directory.Packages.props
index 4ae02af2..6d1dd95c 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -8,10 +8,12 @@
+
+
-
-
-
+
+
+
@@ -30,4 +32,4 @@
-
+
\ No newline at end of file
diff --git a/Speckle.Sdk.sln b/Speckle.Sdk.sln
index bb0e5bbd..5883f32e 100644
--- a/Speckle.Sdk.sln
+++ b/Speckle.Sdk.sln
@@ -42,6 +42,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Tests.Performance", "tests\Speckle.Sdk.Tests.Performance\Speckle.Sdk.Tests.Performance.csproj", "{870E3396-E6F7-43AE-B120-E651FA4F46BD}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Performance.Testing", "tests\Speckle.Sdk.Performance.Testing\Speckle.Sdk.Performance.Testing.csproj", "{F3423F2A-3C83-4F4A-94CF-5D2214BF6CC9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -84,6 +86,10 @@ Global
{870E3396-E6F7-43AE-B120-E651FA4F46BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{870E3396-E6F7-43AE-B120-E651FA4F46BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{870E3396-E6F7-43AE-B120-E651FA4F46BD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F3423F2A-3C83-4F4A-94CF-5D2214BF6CC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F3423F2A-3C83-4F4A-94CF-5D2214BF6CC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F3423F2A-3C83-4F4A-94CF-5D2214BF6CC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F3423F2A-3C83-4F4A-94CF-5D2214BF6CC9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A413E196-3696-4F48-B635-04B5F76BF9C9} = {5CB96C27-FC5B-4A41-86B6-951AF99B8116}
@@ -95,5 +101,6 @@ Global
{4FB41A6D-D139-4111-8115-E3F9F6BEAF24} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
{B623BD21-5CAA-43F9-A539-1835276C220E} = {DA2AED52-58F9-471E-8AD8-102FD36129E3}
{870E3396-E6F7-43AE-B120-E651FA4F46BD} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
+ {F3423F2A-3C83-4F4A-94CF-5D2214BF6CC9} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
EndGlobalSection
EndGlobal
diff --git a/src/Speckle.Objects/packages.lock.json b/src/Speckle.Objects/packages.lock.json
index bf429349..a9e35e79 100644
--- a/src/Speckle.Objects/packages.lock.json
+++ b/src/Speckle.Objects/packages.lock.json
@@ -168,8 +168,8 @@
},
"System.Buffers": {
"type": "Transitive",
- "resolved": "4.4.0",
- "contentHash": "AwarXzzoDwX6BgrhjoJsk6tUezZEozOT5Y9QKF94Gl4JK91I4PIIBkBco9068Y9/Dra8Dkbie99kXB8+1BaYKw=="
+ "resolved": "4.5.1",
+ "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
@@ -178,12 +178,12 @@
},
"System.Memory": {
"type": "Transitive",
- "resolved": "4.5.3",
- "contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==",
+ "resolved": "4.5.5",
+ "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"dependencies": {
- "System.Buffers": "4.4.0",
+ "System.Buffers": "4.5.1",
"System.Numerics.Vectors": "4.4.0",
- "System.Runtime.CompilerServices.Unsafe": "4.5.2"
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.Numerics.Vectors": {
@@ -238,6 +238,8 @@
"Microsoft.Data.Sqlite": "[7.0.7, )",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0, )",
"Microsoft.Extensions.Logging": "[2.2.0, )",
+ "Microsoft.Extensions.ObjectPool": "[8.0.8, )",
+ "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )",
"Polly": "[7.2.3, )",
"Polly.Contrib.WaitAndRetry": "[1.1.1, )",
"Polly.Extensions.Http": "[3.0.0, )",
@@ -290,6 +292,21 @@
"Microsoft.Extensions.Options": "2.2.0"
}
},
+ "Microsoft.Extensions.ObjectPool": {
+ "type": "CentralTransitive",
+ "requested": "[8.0.8, )",
+ "resolved": "8.0.8",
+ "contentHash": "wnjTFjEvvSbOs3iMfl6CeJcUgPHZMYUB9uAQbGQGxGwVRl4GydNpMSkVntTzoi7AqQeYumU9yDSNeVbpq+ebow=="
+ },
+ "Microsoft.IO.RecyclableMemoryStream": {
+ "type": "CentralTransitive",
+ "requested": "[3.0.1, )",
+ "resolved": "3.0.1",
+ "contentHash": "s/s20YTVY9r9TPfTrN5g8zPF1YhwxyqO6PxUkrYTGI2B+OGPe9AdajWZrLhFqXIvqIW23fnUE4+ztrUWNU1+9g==",
+ "dependencies": {
+ "System.Memory": "4.5.5"
+ }
+ },
"Polly": {
"type": "CentralTransitive",
"requested": "[7.2.3, )",
@@ -498,6 +515,8 @@
"Microsoft.Data.Sqlite": "[7.0.7, )",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0, )",
"Microsoft.Extensions.Logging": "[2.2.0, )",
+ "Microsoft.Extensions.ObjectPool": "[8.0.8, )",
+ "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )",
"Polly": "[7.2.3, )",
"Polly.Contrib.WaitAndRetry": "[1.1.1, )",
"Polly.Extensions.Http": "[3.0.0, )",
@@ -550,6 +569,18 @@
"Microsoft.Extensions.Options": "2.2.0"
}
},
+ "Microsoft.Extensions.ObjectPool": {
+ "type": "CentralTransitive",
+ "requested": "[8.0.8, )",
+ "resolved": "8.0.8",
+ "contentHash": "wnjTFjEvvSbOs3iMfl6CeJcUgPHZMYUB9uAQbGQGxGwVRl4GydNpMSkVntTzoi7AqQeYumU9yDSNeVbpq+ebow=="
+ },
+ "Microsoft.IO.RecyclableMemoryStream": {
+ "type": "CentralTransitive",
+ "requested": "[3.0.1, )",
+ "resolved": "3.0.1",
+ "contentHash": "s/s20YTVY9r9TPfTrN5g8zPF1YhwxyqO6PxUkrYTGI2B+OGPe9AdajWZrLhFqXIvqIW23fnUE4+ztrUWNU1+9g=="
+ },
"Polly": {
"type": "CentralTransitive",
"requested": "[7.2.3, )",
diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs
index 9c3e7536..0354844e 100644
--- a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs
+++ b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs
@@ -140,9 +140,7 @@ public async Task Receive(
}
// Shoot out the total children count, wasteful
- var count = (
- await ClosureParser.GetClosuresAsync(objString, localTransport.CancellationToken).ConfigureAwait(false)
- ).Count;
+ var count = ClosureParser.GetClosures(objString).Count;
onTotalChildrenCountKnown?.Invoke(count);
diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs
index 7670484e..4f55c302 100644
--- a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs
+++ b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs
@@ -142,7 +142,7 @@ internal static async Task SerializerSend(
)
{
string obj = serializer.Serialize(value);
- Task[] transportAwaits = serializer.WriteTransports.Select(t => t.WriteComplete()).ToArray();
+ Task[] transportAwaits = serializer.WriteTransports.Select(t => t.WriteComplete().AsTask()).ToArray();
cancellationToken.ThrowIfCancellationRequested();
diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs b/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs
index 1c2e3cd3..2efb8355 100644
--- a/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs
+++ b/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs
@@ -24,6 +24,12 @@ public string Serialize(Base value, CancellationToken cancellationToken = defaul
return serializer.Serialize(value);
}
+ public string Serialize2(Base value, CancellationToken cancellationToken = default)
+ {
+ var serializer = new SpeckleObjectSerializer2 { CancellationToken = cancellationToken };
+ return serializer.Serialize(value);
+ }
+
///
/// Note: if you want to pull an object from a Speckle Transport or Server,
/// please use
diff --git a/src/Speckle.Sdk/Helpers/SerializerIdWriter2.cs b/src/Speckle.Sdk/Helpers/SerializerIdWriter2.cs
new file mode 100644
index 00000000..639d851e
--- /dev/null
+++ b/src/Speckle.Sdk/Helpers/SerializerIdWriter2.cs
@@ -0,0 +1,622 @@
+using Speckle.Newtonsoft.Json;
+
+namespace Speckle.Sdk.Helpers;
+
+public sealed class SerializerIdWriter2 : JsonWriter
+{
+ private readonly JsonWriter _jsonWriter;
+#pragma warning disable CA2213
+ private readonly JsonTextWriter _jsonIdWriter;
+#pragma warning restore CA2213
+ private readonly StringWriter _idWriter;
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ _idWriter.Dispose();
+ }
+
+ public SerializerIdWriter2(JsonWriter jsonWriter, SpeckleObjectSerializer2Pool pool)
+ {
+ _jsonWriter = jsonWriter;
+ _idWriter = new StringWriter();
+ _jsonIdWriter = pool.GetJsonTextWriter(_idWriter);
+ }
+
+ public string FinishIdWriter()
+ {
+ _jsonIdWriter.WriteEndObject();
+ _jsonIdWriter.Flush();
+ var json = _idWriter.ToString();
+ ((IDisposable)_jsonIdWriter).Dispose();
+ return json;
+ }
+
+ public override void WriteValue(string? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteStartArray()
+ {
+ _jsonWriter.WriteStartArray();
+ _jsonIdWriter.WriteStartArray();
+ }
+
+ public override void WriteEndArray()
+ {
+ _jsonWriter.WriteEndArray();
+ _jsonIdWriter.WriteEndArray();
+ }
+
+ public override void WriteStartObject()
+ {
+ _jsonWriter.WriteStartObject();
+ _jsonIdWriter.WriteStartObject();
+ }
+
+ public override void WriteEndObject()
+ {
+ _jsonWriter.WriteEndObject();
+ _jsonIdWriter.WriteEndObject();
+ }
+
+ public override void WriteComment(string? text)
+ {
+ _jsonWriter.WriteComment(text);
+ _jsonIdWriter.WriteComment(text);
+ }
+
+ public override void WritePropertyName(string name)
+ {
+ _jsonWriter.WritePropertyName(name);
+ _jsonIdWriter.WritePropertyName(name);
+ }
+
+ public override void WriteNull()
+ {
+ _jsonWriter.WriteNull();
+ _jsonIdWriter.WriteNull();
+ }
+
+ public override void WriteUndefined()
+ {
+ _jsonWriter.WriteUndefined();
+ _jsonIdWriter.WriteUndefined();
+ }
+
+ public override void WriteRaw(string? json)
+ {
+ _jsonWriter.WriteRaw(json);
+ _jsonIdWriter.WriteRaw(json);
+ }
+
+ public override void WriteRawValue(string? json)
+ {
+ _jsonWriter.WriteRawValue(json);
+ _jsonIdWriter.WriteRawValue(json);
+ }
+
+ public override void WriteValue(bool value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(bool? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(byte value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(byte? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(char value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(char? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(DateTime value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(DateTime? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(DateTimeOffset value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(DateTimeOffset? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(decimal value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(decimal? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(double value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(double? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(float value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(float? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(Guid value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(Guid? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(int value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(int? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(long value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(long? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(sbyte value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(sbyte? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(short value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(short? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(TimeSpan value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(TimeSpan? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(uint value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(uint? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(ulong value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(ulong? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(Uri? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(ushort value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(ushort? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(byte[]? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void WriteValue(object? value)
+ {
+ _jsonWriter.WriteValue(value);
+ _jsonIdWriter.WriteValue(value);
+ }
+
+ public override void Flush()
+ {
+ _jsonWriter.Flush();
+ _jsonIdWriter.Flush();
+ }
+
+ public override async Task WriteValueAsync(string? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteStartArrayAsync(CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteStartArrayAsync(cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteStartArrayAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteEndArrayAsync(CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteEndArrayAsync(cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteEndArrayAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteStartObjectAsync(CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteStartObjectAsync(cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteStartObjectAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteEndObjectAsync(CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteEndObjectAsync(cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteEndObjectAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteCommentAsync(text, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteCommentAsync(text, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WritePropertyNameAsync(string name, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WritePropertyNameAsync(name, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WritePropertyNameAsync(name, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteNullAsync(CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteNullAsync(cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteNullAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteUndefinedAsync(CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteUndefinedAsync(cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteUndefinedAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteRawAsync(string? json, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteRawAsync(json, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteRawAsync(json, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteRawValueAsync(json, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteRawValueAsync(json, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(bool value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(bool? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(byte value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(byte? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(char value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(char? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(DateTime value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(DateTime? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(decimal value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(decimal? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(double value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(double? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(float value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(float? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(Guid value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(Guid? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(int value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(int? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(long value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(long? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(sbyte value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(sbyte? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(short value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(short? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(TimeSpan value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(TimeSpan? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(uint value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(uint? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(ulong value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(ulong? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(ushort value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(ushort? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task WriteValueAsync(object? value, CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.WriteValueAsync(value, cancellationToken).ConfigureAwait(false);
+ }
+
+ public override async Task FlushAsync(CancellationToken cancellationToken = default)
+ {
+ await _jsonWriter.FlushAsync(cancellationToken).ConfigureAwait(false);
+ await _jsonIdWriter.FlushAsync(cancellationToken).ConfigureAwait(false);
+ }
+}
diff --git a/src/Speckle.Sdk/Helpers/SpeckleObjectSerializer2Pool.cs b/src/Speckle.Sdk/Helpers/SpeckleObjectSerializer2Pool.cs
new file mode 100644
index 00000000..7223797c
--- /dev/null
+++ b/src/Speckle.Sdk/Helpers/SpeckleObjectSerializer2Pool.cs
@@ -0,0 +1,40 @@
+using System.Buffers;
+using Microsoft.Extensions.ObjectPool;
+using Speckle.Newtonsoft.Json;
+using Speckle.Sdk.Common;
+
+namespace Speckle.Sdk.Helpers;
+
+public class SpeckleObjectSerializer2Pool
+{
+ public static readonly SpeckleObjectSerializer2Pool Instance = new();
+
+ private SpeckleObjectSerializer2Pool() { }
+
+ public JsonTextWriter GetJsonTextWriter(TextWriter writer) => new(writer) { ArrayPool = _charPool };
+
+ public JsonTextReader GetJsonTextReader(TextReader reader) => new(reader) { ArrayPool = _charPool };
+
+ private readonly SerializerPool _charPool = new(ArrayPool.Create(4096, 4096));
+
+ private class SerializerPool(ArrayPool pool) : IArrayPool
+ {
+ public T[] Rent(int minimumLength) => pool.Rent(minimumLength);
+
+ public void Return(T[]? array) => pool.Return(array.NotNull());
+ }
+
+ public ObjectPool> DictPool { get; } =
+ new DefaultObjectPoolProvider().Create(new DictPoolPolicy());
+
+ private class DictPoolPolicy : PooledObjectPolicy>
+ {
+ public override Dictionary Create() => new(StringComparer.OrdinalIgnoreCase);
+
+ public override bool Return(Dictionary obj)
+ {
+ obj.Clear();
+ return true;
+ }
+ }
+}
diff --git a/src/Speckle.Sdk/Serialisation/BaseObjectDeserializerV2.cs b/src/Speckle.Sdk/Serialisation/BaseObjectDeserializerV2.cs
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs b/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs
index 84b99404..97e79af2 100644
--- a/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs
+++ b/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs
@@ -139,7 +139,7 @@ public async Task DeserializeAsync(string rootObjectJson)
if (propName == "__closure")
{
await reader.ReadAsync(ct).ConfigureAwait(false); //goes to prop value
- var closures = await ClosureParser.GetClosuresAsync(reader).ConfigureAwait(false);
+ var closures = ClosureParser.GetClosures(reader);
foreach (var closure in closures)
{
_ids.Add(closure.Item1);
diff --git a/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer2.cs b/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer2.cs
new file mode 100644
index 00000000..03dec3c0
--- /dev/null
+++ b/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer2.cs
@@ -0,0 +1,352 @@
+using System.Collections.Concurrent;
+using System.Numerics;
+using System.Reflection;
+using Speckle.Newtonsoft.Json;
+using Speckle.Sdk.Common;
+using Speckle.Sdk.Helpers;
+using Speckle.Sdk.Host;
+using Speckle.Sdk.Models;
+using Speckle.Sdk.Serialisation.Utilities;
+using Speckle.Sdk.Transports;
+
+namespace Speckle.Sdk.Serialisation;
+
+public sealed class SpeckleObjectDeserializer2
+{
+ public SpeckleObjectSerializer2Pool Pool { get; } = SpeckleObjectSerializer2Pool.Instance;
+ private bool _isBusy;
+ private readonly object _callbackLock = new();
+ private readonly object?[] _invokeNull = [null];
+
+ // id -> Base if already deserialized or id -> Task