Skip to content

Commit

Permalink
Commit Utf8JsonWriter contents to buffer before writing directly to b… (
Browse files Browse the repository at this point in the history
#2985)

* Commit Utf8JsonWriter contents to buffer before writing directly to bufferwriter in StartStreamValueScopeAsync

* update changes

* update changes
  • Loading branch information
ElizabethOkerio authored Jun 3, 2024
1 parent 9383d7e commit 711f621
Show file tree
Hide file tree
Showing 9 changed files with 802 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/Microsoft.OData.Core/Json/ODataUtf8JsonWriter.Stream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ public void EndStreamValueScope()
/// <returns>A task representing the asynchronous operation. The task result contains a stream for writing the stream value.</returns>
public async Task<Stream> StartStreamValueScopeAsync()
{
this.WriteSeparatorIfNecessary();
this.CommitUtf8JsonWriterContentsToBuffer();
this.WriteItemWithSeparatorIfNeeded();
this.bufferWriter.Write(this.DoubleQuote.Slice(0, 1).Span);

await this.FlushIfBufferThresholdReachedAsync().ConfigureAwait(false);

this.binaryValueStream = new ODataUtf8JsonWriteStream(this);
Expand Down
62 changes: 62 additions & 0 deletions src/Microsoft.OData.Core/Json/ODataUtf8JsonWriter.TextWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,21 @@ private bool CheckIfWritingJson(string currentContentType)
internal sealed class ODataUtf8JsonTextWriter : TextWriter
{
private readonly ODataUtf8JsonWriter jsonWriter = null;
/// <summary>
/// Buffer used to store characters that could not be encoded due to
/// insufficient data in the input buffer. These characters will be prepended
/// to the next chunk of input.
/// </summary>
private char[] buffer;
/// <summary>
/// Number of characters in the buffer that are left over from the previous chunk.
/// </summary>
private int numOfCharsNotWrittenFromPreviousChunk = 0;
/// <summary>
/// This buffer is used by the Write(char) method to store a single character,
/// that we can reuse the methods for writing chars in chunks.
/// </summary>
private char[] singleCharBuffer;

public ODataUtf8JsonTextWriter(ODataUtf8JsonWriter jsonWriter)
{
Expand Down Expand Up @@ -183,6 +196,11 @@ protected override void Dispose(bool disposing)
ArrayPool<char>.Shared.Return(this.buffer);
}

if (this.singleCharBuffer != null)
{
ArrayPool<char>.Shared.Return(this.singleCharBuffer);
}

this.Flush();
base.Dispose(disposing);
}
Expand All @@ -198,9 +216,53 @@ public override async ValueTask DisposeAsync()
ArrayPool<char>.Shared.Return(this.buffer);
}

if (this.singleCharBuffer != null)
{
ArrayPool<char>.Shared.Return(this.singleCharBuffer);
}

await this.FlushAsync().ConfigureAwait(false);
}

/// <summary>
/// Writes the specified character to the ODataUtf8JsonWriter.
/// </summary>
/// <param name="value">The character to write.</param>
public override void Write(char value)
{
if (!this.jsonWriter.isWritingJson)
{
ReadOnlySpan<char> charToWrite = stackalloc char[1] { value };
this.WriteCharsInChunks(charToWrite);
}
else
{
ReadOnlySpan<char> charToWrite = stackalloc char[1] { value };
this.WriteCharsInChunksWithoutEscaping(charToWrite);
}
}

/// <summary>
/// Asynchronously writes the specified character to the ODataUtf8JsonWriter.
/// </summary>
/// <param name="value">The character to write.</param>
public override async Task WriteAsync(char value)
{
this.singleCharBuffer ??= ArrayPool<char>.Shared.Rent(1);
this.singleCharBuffer[0] = value;
ReadOnlyMemory<char> input = this.singleCharBuffer.AsMemory().Slice(0, 1);

if (!this.jsonWriter.isWritingJson)
{

await this.WriteCharsInChunksAsync(input).ConfigureAwait(false);
}
else
{
await this.WriteCharsInChunksWithoutEscapingAsync(input).ConfigureAwait(false);
}
}

/// <summary>
/// Writes a specified number of characters from the given character array to the ODataUtf8JsonWriter.
/// </summary>
Expand Down
38 changes: 36 additions & 2 deletions src/Microsoft.OData.Core/Json/ODataUtf8JsonWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Microsoft.OData.Edm;
using System.Text.Unicode;
using System.Buffers.Text;
using System.Xml;

namespace Microsoft.OData.Json
{
Expand Down Expand Up @@ -252,7 +253,24 @@ public void WriteValue(int value)
public void WriteValue(float value)
{
this.WriteSeparatorIfNecessary();
this.utf8JsonWriter.WriteNumberValue(value);

if (float.IsNaN(value))
{
this.utf8JsonWriter.WriteStringValue(nanValue.Span);
}
else if (float.IsPositiveInfinity(value))
{
this.utf8JsonWriter.WriteStringValue(positiveInfinityValue.Span);
}
else if (float.IsNegativeInfinity(value))
{
this.utf8JsonWriter.WriteStringValue(negativeInfinityValue.Span);
}
else
{
this.utf8JsonWriter.WriteNumberValue(value);
}

this.FlushIfBufferThresholdReached();
}

Expand Down Expand Up @@ -936,7 +954,23 @@ public async Task WriteValueAsync(int value)
public async Task WriteValueAsync(float value)
{
this.WriteSeparatorIfNecessary();
this.utf8JsonWriter.WriteNumberValue(value);
if (float.IsNaN(value))
{
this.utf8JsonWriter.WriteStringValue(nanValue.Span);
}
else if (float.IsPositiveInfinity(value))
{
this.utf8JsonWriter.WriteStringValue(positiveInfinityValue.Span);
}
else if (float.IsNegativeInfinity(value))
{
this.utf8JsonWriter.WriteStringValue(negativeInfinityValue.Span);
}
else
{
this.utf8JsonWriter.WriteNumberValue(value);
}

await this.FlushIfBufferThresholdReachedAsync().ConfigureAwait(false);
}

Expand Down
Loading

0 comments on commit 711f621

Please sign in to comment.