Skip to content

Commit aaea31a

Browse files
committed
Add ReadOnlySpan<byte> and ReadOnlySpan<char> overloads to TransportSerializerExtensions
1 parent a3f1378 commit aaea31a

File tree

3 files changed

+131
-9
lines changed

3 files changed

+131
-9
lines changed

src/Elastic.Transport/Components/Serialization/Serializer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public abstract class Serializer
3232
/// <inheritdoc cref="Deserialize"/>
3333
public abstract ValueTask<T> DeserializeAsync<T>(Stream stream, CancellationToken cancellationToken = default);
3434

35+
// TODO: Overloads for (object?, Type) inputs
36+
3537
/// <summary>
3638
/// Serialize an instance of <typeparamref name="T"/> to <paramref name="stream"/> using <paramref name="formatting"/>.
3739
/// </summary>

src/Elastic.Transport/Components/Serialization/SystemTextJsonSerializer.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,10 @@ protected virtual void Initialized()
110110
/// </summary>
111111
/// <param name="formatting">The serialization formatting.</param>
112112
/// <returns>The requested <see cref="JsonSerializerOptions"/> or <c>null</c>, if the serializer is not initialized yet.</returns>
113-
protected internal JsonSerializerOptions? GetJsonSerializerOptions(SerializationFormatting formatting) => (formatting is SerializationFormatting.None)
114-
? _options
115-
: _indentedOptions;
113+
protected internal JsonSerializerOptions? GetJsonSerializerOptions(SerializationFormatting formatting = SerializationFormatting.None) =>
114+
(formatting is SerializationFormatting.None)
115+
? _options
116+
: _indentedOptions;
116117

117118
/// <summary>
118119
/// Initializes a serializer instance such that its <see cref="JsonSerializerOptions"/> are populated.

src/Elastic.Transport/Components/Serialization/TransportSerializerExtensions.cs

Lines changed: 125 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.IO;
66
using System.Text.Json;
77
using System;
8+
using System.Text;
89
using System.Text.Json.Nodes;
910

1011
namespace Elastic.Transport.Extensions;
@@ -80,6 +81,124 @@ public static string SerializeToString<T>(
8081

8182
#region STJ Extensions
8283

84+
/// <summary>
85+
/// Extension method that deserializes from a UTF8 <see cref="ReadOnlySpan{T}"/>.
86+
/// </summary>
87+
/// <typeparam name="T">The type of the data to be deserialized.</typeparam>
88+
/// <param name="serializer"><inheritdoc cref="Serializer" path="/summary"/></param>
89+
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> that contains the UTF8 encoded JSON string.</param>
90+
/// <param name="memoryStreamFactory">
91+
/// A factory yielding <see cref="MemoryStream"/> instances, defaults to <see cref="RecyclableMemoryStreamFactory"/>
92+
/// that yields memory streams backed by pooled byte arrays.
93+
/// </param>
94+
/// <returns>The deserialized data.</returns>
95+
public static T? Deserialize<T>(
96+
this Serializer serializer,
97+
ReadOnlySpan<byte> span,
98+
MemoryStreamFactory? memoryStreamFactory = null)
99+
{
100+
if (serializer is SystemTextJsonSerializer stjSerializer)
101+
{
102+
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
103+
// deserialize straight from the span.
104+
return JsonSerializer.Deserialize<T>(span, stjSerializer.GetJsonSerializerOptions());
105+
}
106+
107+
memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
108+
using var ms = memoryStreamFactory.Create(span.ToArray());
109+
110+
return serializer.Deserialize<T>(ms);
111+
}
112+
113+
/// <summary>
114+
/// Extension method that deserializes from a UTF8 <see cref="ReadOnlySpan{T}"/>.
115+
/// </summary>
116+
/// <param name="serializer"><inheritdoc cref="Serializer" path="/summary"/></param>
117+
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> that contains the UTF8 encoded JSON.</param>
118+
/// <param name="type">The type of the data to be deserialized.</param>
119+
/// <param name="memoryStreamFactory">
120+
/// A factory yielding <see cref="MemoryStream"/> instances, defaults to <see cref="RecyclableMemoryStreamFactory"/>
121+
/// that yields memory streams backed by pooled byte arrays.
122+
/// </param>
123+
/// <returns>The deserialized data.</returns>
124+
public static object? Deserialize(
125+
this Serializer serializer,
126+
ReadOnlySpan<byte> span,
127+
Type type,
128+
MemoryStreamFactory? memoryStreamFactory = null)
129+
{
130+
if (serializer is SystemTextJsonSerializer stjSerializer)
131+
{
132+
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
133+
// deserialize straight from the span.
134+
return JsonSerializer.Deserialize(span, type, stjSerializer.GetJsonSerializerOptions());
135+
}
136+
137+
memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
138+
using var ms = memoryStreamFactory.Create(span.ToArray());
139+
140+
return serializer.Deserialize(type, ms);
141+
}
142+
143+
/// <summary>
144+
/// Extension method that deserializes from a UTF8 <see cref="ReadOnlySpan{T}"/>.
145+
/// </summary>
146+
/// <typeparam name="T">The type of the data to be deserialized.</typeparam>
147+
/// <param name="serializer"><inheritdoc cref="Serializer" path="/summary"/></param>
148+
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> that contains the UTF8 encoded JSON string.</param>
149+
/// <param name="memoryStreamFactory">
150+
/// A factory yielding <see cref="MemoryStream"/> instances, defaults to <see cref="RecyclableMemoryStreamFactory"/>
151+
/// that yields memory streams backed by pooled byte arrays.
152+
/// </param>
153+
/// <returns>The deserialized data.</returns>
154+
public static T? Deserialize<T>(
155+
this Serializer serializer,
156+
ReadOnlySpan<char> span,
157+
MemoryStreamFactory? memoryStreamFactory = null)
158+
{
159+
if (serializer is SystemTextJsonSerializer stjSerializer)
160+
{
161+
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
162+
// deserialize straight from the span.
163+
return JsonSerializer.Deserialize<T>(span, stjSerializer.GetJsonSerializerOptions());
164+
}
165+
166+
memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
167+
using var ms = memoryStreamFactory.Create(Encoding.UTF8.GetBytes(span.ToArray()));
168+
169+
return serializer.Deserialize<T>(ms);
170+
}
171+
172+
/// <summary>
173+
/// Extension method that deserializes from a UTF8 <see cref="ReadOnlySpan{T}"/>.
174+
/// </summary>
175+
/// <param name="serializer"><inheritdoc cref="Serializer" path="/summary"/></param>
176+
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> that contains the UTF8 encoded JSON.</param>
177+
/// <param name="type">The type of the data to be deserialized.</param>
178+
/// <param name="memoryStreamFactory">
179+
/// A factory yielding <see cref="MemoryStream"/> instances, defaults to <see cref="RecyclableMemoryStreamFactory"/>
180+
/// that yields memory streams backed by pooled byte arrays.
181+
/// </param>
182+
/// <returns>The deserialized data.</returns>
183+
public static object? Deserialize(
184+
this Serializer serializer,
185+
ReadOnlySpan<char> span,
186+
Type type,
187+
MemoryStreamFactory? memoryStreamFactory = null)
188+
{
189+
if (serializer is SystemTextJsonSerializer stjSerializer)
190+
{
191+
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
192+
// deserialize straight from the span.
193+
return JsonSerializer.Deserialize(span, type, stjSerializer.GetJsonSerializerOptions());
194+
}
195+
196+
memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
197+
using var ms = memoryStreamFactory.Create(Encoding.UTF8.GetBytes(span.ToArray()));
198+
199+
return serializer.Deserialize(type, ms);
200+
}
201+
83202
/// <summary>
84203
/// Extension method that writes the serialized representation of an instance of <typeparamref name="T"/> to a
85204
/// <see cref="Utf8JsonWriter"/>.
@@ -185,7 +304,7 @@ public static void Serialize(
185304
{
186305
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
187306
// deserialize straight from the reader.
188-
return JsonSerializer.Deserialize<T>(ref reader, stjSerializer.GetJsonSerializerOptions(SerializationFormatting.None));
307+
return JsonSerializer.Deserialize<T>(ref reader, stjSerializer.GetJsonSerializerOptions());
189308
}
190309

191310
using var jsonDoc = JsonSerializer.Deserialize<JsonDocument>(ref reader);
@@ -222,7 +341,7 @@ public static void Serialize(
222341
{
223342
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
224343
// deserialize straight from the reader.
225-
return JsonSerializer.Deserialize(ref reader, type, stjSerializer.GetJsonSerializerOptions(SerializationFormatting.None));
344+
return JsonSerializer.Deserialize(ref reader, type, stjSerializer.GetJsonSerializerOptions());
226345
}
227346

228347
using var jsonDoc = JsonSerializer.Deserialize<JsonDocument>(ref reader);
@@ -258,7 +377,7 @@ public static void Serialize(
258377
{
259378
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
260379
// deserialize straight from the node.
261-
return node.Deserialize<T>(stjSerializer.GetJsonSerializerOptions(SerializationFormatting.None));
380+
return node.Deserialize<T>(stjSerializer.GetJsonSerializerOptions());
262381
}
263382

264383
memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
@@ -293,7 +412,7 @@ public static void Serialize(
293412
{
294413
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
295414
// deserialize straight from the node.
296-
return node.Deserialize(type, stjSerializer.GetJsonSerializerOptions(SerializationFormatting.None));
415+
return node.Deserialize(type, stjSerializer.GetJsonSerializerOptions());
297416
}
298417

299418
memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
@@ -327,7 +446,7 @@ public static void Serialize(
327446
{
328447
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
329448
// deserialize straight from the node.
330-
return node.Deserialize<T>(stjSerializer.GetJsonSerializerOptions(SerializationFormatting.None));
449+
return node.Deserialize<T>(stjSerializer.GetJsonSerializerOptions());
331450
}
332451

333452
memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;
@@ -362,7 +481,7 @@ public static void Serialize(
362481
{
363482
// When the serializer derives from `SystemTextJsonSerializer` we can avoid unnecessary allocations and
364483
// deserialize straight from the node.
365-
return node.Deserialize(type, stjSerializer.GetJsonSerializerOptions(SerializationFormatting.None));
484+
return node.Deserialize(type, stjSerializer.GetJsonSerializerOptions());
366485
}
367486

368487
memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory;

0 commit comments

Comments
 (0)