-
Notifications
You must be signed in to change notification settings - Fork 337
Add support for BufferWriter<T> to the JsonWriter where T is IBufferWriter<byte> #2358
Changes from all commits
0f455ed
7f106c8
57574db
45a103b
090feac
9c8e666
5370b7b
1d26049
e5f7f1b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
| using System.Threading; | ||
| using System.Text.Http.Parser; | ||
| using Microsoft.Net; | ||
| using System.Buffers.Writer; | ||
|
|
||
| namespace LowAllocationWebServer | ||
| { | ||
|
|
@@ -62,7 +63,7 @@ static void WriteResponseForGetJson(HttpRequest request, ReadOnlySequence<byte> | |
| response.AppendEoh(); | ||
|
|
||
| // write response JSON | ||
| var jsonWriter = new JsonWriter(response, true, prettyPrint: false); | ||
| var jsonWriter = new JsonWriter(new BufferWriter<IBufferWriter<byte>>(response), true, prettyPrint: false); | ||
| jsonWriter.WriteObjectStart(); | ||
| jsonWriter.WriteArrayStart("values"); | ||
| for (int i = 0; i < 5; i++) | ||
|
|
@@ -94,7 +95,7 @@ static void WriteResponseForPostJson(HttpRequest request, ReadOnlySequence<byte> | |
| response.AppendEoh(); | ||
|
|
||
| // write response JSON | ||
| var jsonWriter = new JsonWriter(response, true, prettyPrint: false); | ||
| var jsonWriter = new JsonWriter(new BufferWriter<IBufferWriter<byte>>(response), true, prettyPrint: false); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. var jsonWriter = JsonWriter.Create(BufferWriter.Create(response), true, prettyPrint: false); |
||
| jsonWriter.WriteObjectStart(); | ||
| jsonWriter.WriteArrayStart("values"); | ||
| for (int i = 0; i < requestedCount; i++) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,30 +3,31 @@ | |
|
|
||
| using System.Buffers; | ||
| using System.Buffers.Text; | ||
| using System.Buffers.Writer; | ||
| using System.Diagnostics; | ||
| using System.Runtime.CompilerServices; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace System.Text.JsonLab | ||
| { | ||
| public struct JsonWriter | ||
| public ref struct JsonWriter | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. public ref struct JsonWriter<TBufferWriter> where TBufferWriter : IBufferWriter<byte>
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you help me understand why that would be beneficial? Also, if we make JsonWriter generic (with the constraint), how can we add support for stream?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Two main reasons
I assume you mean something not currently present? Make a struct wrapper for Stream and provide a public struct StreamWriter : IBufferWriter<byte>
{
private Stream _stream;
public StreamWriter(Stream stream)
{
_stream = stream;
}
public void Advance(int count)
{
// ...
}
public Memory<byte> GetMemory(int sizeHint = 0)
{
// ...
}
public Span<byte> GetSpan(int sizeHint = 0)
{
// ...
}
}
public static class JsonWriter
{
public static JsonWriter<TBufferWriter> Create<TBufferWriter>(
TBufferWriter bufferWriter,
bool isUtf8,
bool prettyPrint = false)
where TBufferWriter : IBufferWriter<byte>
{
return new JsonWriter<TBufferWriter>(bufferWriter, isUtf8, prettyPrint);
}
// Stream overload
public static JsonWriter<StreamWriter> Create(
Stream stream,
bool isUtf8,
bool prettyPrint = false)
{
return new JsonWriter<StreamWriter>(new StreamWriter(stream), isUtf8, prettyPrint);
}
}
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@benaadams is related to CLR behaviour explained here https://blogs.msdn.microsoft.com/joelpob/2004/11/17/clr-generics-and-code-sharing/ ?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes.
That is a great idea! I was trying to see if there was a way to add stream support directly to JsonWriter without exposing additional public types (like the StreamWriter wrapper). However, the boxing and performance benefits you mentioned are definitely compelling.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I wasn't seeing any allocations because the formatter used within the benchmarks is a class (ArrayFormatter). Good point.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, missed that. Can always measure the effects of the call costs by creating a second struct that just wraps and using that in a test instead of public struct ArrayFormatterWrapper : ITextBufferWriter, IDisposable
{
private ArrayFormatter _arrayFormatter;
public ArrayFormatter(int capacity, SymbolTable symbolTable, ArrayPool<byte> pool = null)
{
_arrayFormatter = new ArrayFormatter(capacity, symbolTable, pool);
}
public int CommitedByteCount => _arrayFormatter.CommitedByteCount;
public void Clear()
{
_arrayFormatter.Clear();
}
public ArraySegment<byte> Free => _arrayFormatter.Free;
public ArraySegment<byte> Formatted => _arrayFormatter.Formatted;
public SymbolTable SymbolTable => _arrayFormatter.SymbolTable;
public Memory<byte> GetMemory(int minimumLength = 0)
{
_arrayFormatter.GetMemory(minimumLength);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<byte> GetSpan(int minimumLength = 0)
{
_arrayFormatter.GetSpan(minimumLength);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Advance(int bytes)
{
_arrayFormatter.Advance(bytes);
}
public int MaxBufferSize { get; } = _arrayFormatter.MaxBufferSize;
public void Dispose()
{
_arrayFormatter.Dispose();
}
} |
||
| { | ||
| private static readonly byte[] s_newLineUtf8 = Encoding.UTF8.GetBytes(Environment.NewLine); | ||
| private static readonly char[] s_newLineUtf16 = Environment.NewLine.ToCharArray(); | ||
|
|
||
| readonly bool _prettyPrint; | ||
| readonly IBufferWriter<byte> _bufferWriter; | ||
| readonly bool _isUtf8; | ||
| private readonly bool _prettyPrint; | ||
| private BufferWriter<IBufferWriter<byte>> _bufferWriter; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. private TBufferWriter _bufferWriter; |
||
| private readonly bool _isUtf8; | ||
|
|
||
| int _indent; | ||
| bool _firstItem; | ||
| private int _indent; | ||
| private bool _firstItem; | ||
|
|
||
| /// <summary> | ||
| /// Constructs a JSON writer with a specified <paramref name="bufferWriter"/>. | ||
| /// </summary> | ||
| /// <param name="bufferWriter">An instance of <see cref="ITextBufferWriter" /> used for writing bytes to an output channel.</param> | ||
| /// <param name="prettyPrint">Specifies whether to add whitespace to the output text for user readability.</param> | ||
| public JsonWriter(IBufferWriter<byte> bufferWriter, bool isUtf8, bool prettyPrint = false) | ||
| public JsonWriter(BufferWriter<IBufferWriter<byte>> bufferWriter, bool isUtf8, bool prettyPrint = false) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. public JsonWriter(TBufferWriter bufferWriter, bool isUtf8, bool prettyPrint = false) |
||
| { | ||
| _bufferWriter = bufferWriter; | ||
| _prettyPrint = prettyPrint; | ||
|
|
@@ -1077,14 +1078,18 @@ public void WriteNull() | |
| } | ||
| } | ||
|
|
||
| public void Flush() => _bufferWriter.Flush(); | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteNumberUtf8(long value) | ||
| { | ||
| //TODO: Optimize, this is too slow | ||
| var buffer = _bufferWriter.GetSpan(); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| int written; | ||
| while (!CustomFormatter.TryFormat(value, buffer, out written, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) | ||
| { | ||
| buffer = EnsureBuffer(); | ||
| } | ||
|
|
||
| _bufferWriter.Advance(written); | ||
| } | ||
|
|
@@ -1093,91 +1098,106 @@ private void WriteNumberUtf8(long value) | |
| private void WriteNumberUtf16(long value) | ||
| { | ||
| //TODO: Optimize, this is too slow | ||
| var buffer = _bufferWriter.GetSpan(); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| int written; | ||
| while (!CustomFormatter.TryFormat(value, buffer, out written, JsonConstants.NumberFormat, SymbolTable.InvariantUtf16)) | ||
| { | ||
| buffer = EnsureBuffer(); | ||
| } | ||
|
|
||
| _bufferWriter.Advance(written); | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteNumber(ulong value) | ||
| { | ||
| var buffer = _bufferWriter.GetSpan(); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| int written; | ||
| while (!CustomFormatter.TryFormat(value, buffer, out written, JsonConstants.NumberFormat, SymbolTable.InvariantUtf8)) | ||
| { | ||
| buffer = EnsureBuffer(); | ||
| } | ||
|
|
||
| _bufferWriter.Advance(written); | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteDateTime(DateTime value) | ||
| { | ||
| var buffer = _bufferWriter.GetSpan(); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| int written; | ||
| while (!CustomFormatter.TryFormat(value, buffer, out written, JsonConstants.DateTimeFormat, SymbolTable.InvariantUtf8)) | ||
| { | ||
| buffer = EnsureBuffer(); | ||
| } | ||
|
|
||
| _bufferWriter.Advance(written); | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteDateTimeOffset(DateTimeOffset value) | ||
| { | ||
| var buffer = _bufferWriter.GetSpan(); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| int written; | ||
| while (!CustomFormatter.TryFormat(value, buffer, out written, JsonConstants.DateTimeFormat, SymbolTable.InvariantUtf8)) | ||
| { | ||
| buffer = EnsureBuffer(); | ||
| } | ||
|
|
||
| _bufferWriter.Advance(written); | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteGuid(Guid value) | ||
| { | ||
| var buffer = _bufferWriter.GetSpan(); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| int written; | ||
| while (!CustomFormatter.TryFormat(value, buffer, out written, JsonConstants.GuidFormat, SymbolTable.InvariantUtf8)) | ||
| { | ||
| buffer = EnsureBuffer(); | ||
| } | ||
|
|
||
| _bufferWriter.Advance(written); | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteJsonValueUtf8(ReadOnlySpan<byte> values) | ||
| { | ||
| var buffer = _bufferWriter.GetSpan(); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| int written; | ||
| while (!SymbolTable.InvariantUtf8.TryEncode(values, buffer, out int consumed, out written)) | ||
| { | ||
| buffer = EnsureBuffer(); | ||
| } | ||
|
|
||
| _bufferWriter.Advance(written); | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteJsonValueUtf16(ReadOnlySpan<byte> values) | ||
| { | ||
| var buffer = _bufferWriter.GetSpan(); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| int written; | ||
| while (!SymbolTable.InvariantUtf16.TryEncode(values, buffer, out int consumed, out written)) | ||
| { | ||
| buffer = EnsureBuffer(); | ||
| } | ||
|
|
||
| _bufferWriter.Advance(written); | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteControlUtf8(byte value) | ||
| { | ||
| MemoryMarshal.GetReference(EnsureBuffer(1)) = value; | ||
| Span<byte> buffer = EnsureBuffer(1); | ||
| MemoryMarshal.GetReference(buffer) = value; | ||
| _bufferWriter.Advance(1); | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private void WriteControlUtf16(byte value) | ||
| { | ||
| var buffer = EnsureBuffer(2); | ||
| Span<byte> buffer = EnsureBuffer(2); | ||
| Unsafe.As<byte, char>(ref MemoryMarshal.GetReference(buffer)) = (char)value; | ||
| _bufferWriter.Advance(2); | ||
| } | ||
|
|
@@ -1210,7 +1230,7 @@ private void WriteSpacingUtf8(bool newline = true) | |
| var bytesNeeded = newline ? 2 : 0; | ||
| bytesNeeded += (indent + 1) * 2; | ||
|
|
||
| var buffer = EnsureBuffer(bytesNeeded); | ||
| Span<byte> buffer = EnsureBuffer(bytesNeeded); | ||
| ref byte utf8Bytes = ref MemoryMarshal.GetReference(buffer); | ||
| int idx = 0; | ||
|
|
||
|
|
@@ -1240,7 +1260,7 @@ private void WriteSpacingUtf16(bool newline = true) | |
| bytesNeeded += (indent + 1) * 2; | ||
| bytesNeeded *= sizeof(char); | ||
|
|
||
| var buffer = EnsureBuffer(bytesNeeded); | ||
| Span<byte> buffer = EnsureBuffer(bytesNeeded); | ||
| var span = MemoryMarshal.Cast<byte, char>(buffer); | ||
| ref char utf16Bytes = ref MemoryMarshal.GetReference(span); | ||
| int idx = 0; | ||
|
|
@@ -1263,10 +1283,10 @@ private void WriteSpacingUtf16(bool newline = true) | |
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private Span<byte> EnsureBuffer(int needed = 256) | ||
| { | ||
| Span<byte> buffer = _bufferWriter.GetSpan(needed); | ||
| _bufferWriter.Ensure(needed); | ||
| Span<byte> buffer = _bufferWriter.Buffer; | ||
| if (buffer.Length < needed) | ||
| JsonThrowHelper.ThrowOutOfMemoryException(); | ||
|
|
||
| return buffer; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,9 @@ | |
| // The .NET Foundation licenses this file to you under the MIT license. | ||
| // See the LICENSE file in the project root for more information. | ||
|
|
||
| using System.Buffers; | ||
| using System.Buffers.Text; | ||
| using System.Buffers.Writer; | ||
| using System.IO.Pipelines.Samples; | ||
| using System.Text; | ||
| using System.Text.Formatting; | ||
|
|
@@ -29,7 +31,8 @@ public class E2E | |
| [Arguments(10000, 256)] | ||
| public void TechEmpowerHelloWorldNoIO(int numberOfRequests, int concurrentConnections) | ||
| { | ||
| RawInMemoryHttpServer.Run(numberOfRequests, concurrentConnections, s_genericRequest, (request, response) => { | ||
| RawInMemoryHttpServer.Run(numberOfRequests, concurrentConnections, s_genericRequest, (request, response) => | ||
| { | ||
| var formatter = new BufferWriterFormatter<PipeWriter>(response, SymbolTable.InvariantUtf8); | ||
| formatter.Append("HTTP/1.1 200 OK"); | ||
| formatter.Append("\r\nContent-Length: 13"); | ||
|
|
@@ -47,7 +50,8 @@ public void TechEmpowerHelloWorldNoIO(int numberOfRequests, int concurrentConnec | |
| [Arguments(10000, 256)] | ||
| public void TechEmpowerJsonNoIO(int numberOfRequests, int concurrentConnections) | ||
| { | ||
| RawInMemoryHttpServer.Run(numberOfRequests, concurrentConnections, s_genericRequest, (request, response) => { | ||
| RawInMemoryHttpServer.Run(numberOfRequests, concurrentConnections, s_genericRequest, (request, response) => | ||
| { | ||
| var formatter = new BufferWriterFormatter<PipeWriter>(response, SymbolTable.InvariantUtf8); | ||
| formatter.Append("HTTP/1.1 200 OK"); | ||
| formatter.Append("\r\nContent-Length: 25"); | ||
|
|
@@ -57,7 +61,7 @@ public void TechEmpowerJsonNoIO(int numberOfRequests, int concurrentConnections) | |
| formatter.Append("\r\n\r\n"); | ||
|
|
||
| // write body | ||
| var writer = new JsonWriter(formatter, true); | ||
| var writer = new JsonWriter(new BufferWriter<IBufferWriter<byte>>(formatter), true, true); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. var writer = new JsonWriter<BufferWriterFormatter<PipeWriter>>(formatter, isUtf8: true, prettyPrint: true);Perhaps add a convenience static Create public static JsonWriter<TBufferWriter> Create<TBufferWriter>(
TBufferWriter bufferWriter,
bool isUtf8,
bool prettyPrint = false)
where TBufferWriter : IBufferWriter<byte>
{
return new JsonWriter<TBufferWriter>(bufferWriter, isUtf8, prettyPrint);
}Then instead it would become var writer = JsonWriter.Create(formatter, isUtf8: true, prettyPrint: true);
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed Create method, had it wrong before; it just needs to pass through the generic type |
||
| writer.WriteObjectStart(); | ||
| writer.WriteAttribute("message", "Hello, World!"); | ||
| writer.WriteObjectEnd(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,7 +2,9 @@ | |||||||
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||||||||
|
|
||||||||
| using BenchmarkDotNet.Attributes; | ||||||||
| using System.Buffers; | ||||||||
| using System.Buffers.Text; | ||||||||
| using System.Buffers.Writer; | ||||||||
| using System.IO; | ||||||||
| using System.Text.Formatting; | ||||||||
|
|
||||||||
|
|
@@ -56,10 +58,11 @@ public void Setup() | |||||||
| public void WriterSystemTextJsonBasic() | ||||||||
| { | ||||||||
| _arrayFormatter.Clear(); | ||||||||
| var bufferWriter = new BufferWriter<IBufferWriter<byte>>(_arrayFormatter); | ||||||||
| if (IsUTF8Encoded) | ||||||||
| WriterSystemTextJsonBasicUtf8(Formatted, _arrayFormatter, _data); | ||||||||
| WriterSystemTextJsonBasicUtf8(Formatted, bufferWriter, _data); | ||||||||
| else | ||||||||
| WriterSystemTextJsonBasicUtf16(Formatted, _arrayFormatter, _data); | ||||||||
| WriterSystemTextJsonBasicUtf16(Formatted, bufferWriter, _data); | ||||||||
| } | ||||||||
|
|
||||||||
| [Benchmark] | ||||||||
|
|
@@ -72,10 +75,11 @@ public void WriterNewtonsoftBasic() | |||||||
| public void WriterSystemTextJsonHelloWorld() | ||||||||
| { | ||||||||
| _arrayFormatter.Clear(); | ||||||||
| var bufferWriter = new BufferWriter<IBufferWriter<byte>>(_arrayFormatter); | ||||||||
| if (IsUTF8Encoded) | ||||||||
| WriterSystemTextJsonHelloWorldUtf8(Formatted, _arrayFormatter); | ||||||||
| WriterSystemTextJsonHelloWorldUtf8(Formatted, bufferWriter); | ||||||||
| else | ||||||||
| WriterSystemTextJsonHelloWorldUtf16(Formatted, _arrayFormatter); | ||||||||
| WriterSystemTextJsonHelloWorldUtf16(Formatted, bufferWriter); | ||||||||
| } | ||||||||
|
|
||||||||
| [Benchmark] | ||||||||
|
|
@@ -100,7 +104,7 @@ private TextWriter GetWriter() | |||||||
| return writer; | ||||||||
| } | ||||||||
|
|
||||||||
| private static void WriterSystemTextJsonBasicUtf8(bool formatted, ArrayFormatter output, int[] data) | ||||||||
| private static void WriterSystemTextJsonBasicUtf8(bool formatted, BufferWriter<IBufferWriter<byte>> output, int[] data) | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again add a convenience helper public ref partial struct BufferWriter
{
public static BufferWriter<T> Create<T>(TBufferWriter bufferWriter) where TBufferWriter : IBufferWriter<byte>
{
return new BufferWriter<TBufferWriter>(bufferWriter);
}
}Though maybe they should be called private static void WriterSystemTextJsonBasicUtf8<TBufferWriter>(bool formatted, TBufferWriter output, int[] data)
where TBufferWriter : IBufferWriter<byte>
{
WriterSystemTextJsonBasicUtf8(formatted, BufferWriter.Create(output), data);
}
private static void WriterSystemTextJsonBasicUtf8(bool formatted, BufferWriter<TBufferWriter> output, int[] data)
where TBufferWriter IBufferWriter<byte>
{
var json = JsonWriter.Create(output, isUtf8: true, formatted);
// ...
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is good feedback specific to BufferWriter.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added comment for issue
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change to overload is still relevant for this PR though
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We already have such a convenience method: corefxlab/src/System.Buffers.ReaderWriter/System/Buffers/Writer/BufferWriter.cs Lines 24 to 26 in a02d39d
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also Severity Code Description Project File Line Suppression State @benaadams, thoughts?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Concrete type it, but not its parameter? public static class JsonWriter
{
public static JsonWriter<TBufferWriter> Create<TBufferWriter>(
TBufferWriter bufferWriter,
bool isUtf8,
bool prettyPrint = false)
where TBufferWriter : IBufferWriter<byte>
{
return new JsonWriter<TBufferWriter>(BufferWriter.Create(bufferWriter), isUtf8, prettyPrint);
}
// Stream overload
public static JsonWriter<StreamWriter> Create(
Stream stream,
bool isUtf8,
bool prettyPrint = false)
{
return new JsonWriter<StreamWriter>(BufferWriter.Create(new StreamWriter(stream)), isUtf8, prettyPrint);
}
}
public ref struct JsonWriter<TBufferWriter>
where TBufferWriter : IBufferWriter<byte>
{
private BufferWriter<TBufferWriter> _bufferWriter;
public JsonWriter(BufferWriter<TBufferWriter> bufferWriter, bool isUtf8, bool prettyPrint = false)
{
_bufferWriter = bufferWriter;
// ...
}
}
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't follow. We still have the issue with JsonWriter.Create since the first argument passed to it is a generic type (TBufferWriter) and bufferWriter is a ref struct: var formatter = new ArrayFormatter(1024, SymbolTable.InvariantUtf8);
var bufferWriter = BufferWriter.Create(formatter);
var json = JsonWriter.Create(bufferWriter, isUtf8: true, prettyPrint: false); // Build errorSeverity Code Description Project File Line Suppression State
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, gotcha. Just need to add concrete Create overload? public static class JsonWriter
{
public static JsonWriter<TBufferWriter> Create<TBufferWriter>(
TBufferWriter bufferWriter,
bool isUtf8,
bool prettyPrint = false)
where TBufferWriter : IBufferWriter<byte>
{
return new JsonWriter<TBufferWriter>(BufferWriter.Create(bufferWriter), isUtf8, prettyPrint);
}
// extra overload
public static JsonWriter<TBufferWriter> Create<TBufferWriter>(
BufferWriter<TBufferWriter> bufferWriter,
bool isUtf8,
bool prettyPrint = false)
where TBufferWriter : IBufferWriter<byte>
{
return new JsonWriter<TBufferWriter>(bufferWriter, isUtf8, prettyPrint);
}
} |
||||||||
| { | ||||||||
| var json = new JsonWriter(output, true, formatted); | ||||||||
|
|
||||||||
|
|
@@ -127,9 +131,10 @@ private static void WriterSystemTextJsonBasicUtf8(bool formatted, ArrayFormatter | |||||||
| json.WriteArrayEnd(); | ||||||||
|
|
||||||||
| json.WriteObjectEnd(); | ||||||||
| json.Flush(); | ||||||||
| } | ||||||||
|
|
||||||||
| private static void WriterSystemTextJsonBasicUtf16(bool formatted, ArrayFormatter output, int[] data) | ||||||||
| private static void WriterSystemTextJsonBasicUtf16(bool formatted, BufferWriter<IBufferWriter<byte>> output, int[] data) | ||||||||
| { | ||||||||
| var json = new JsonWriter(output, false, formatted); | ||||||||
|
|
||||||||
|
|
@@ -156,6 +161,7 @@ private static void WriterSystemTextJsonBasicUtf16(bool formatted, ArrayFormatte | |||||||
| json.WriteArrayEnd(); | ||||||||
|
|
||||||||
| json.WriteObjectEnd(); | ||||||||
| json.Flush(); | ||||||||
| } | ||||||||
|
|
||||||||
| private static void WriterNewtonsoftBasic(bool formatted, TextWriter writer, int[] data) | ||||||||
|
|
@@ -199,22 +205,24 @@ private static void WriterNewtonsoftBasic(bool formatted, TextWriter writer, int | |||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| private static void WriterSystemTextJsonHelloWorldUtf8(bool formatted, ArrayFormatter output) | ||||||||
| private static void WriterSystemTextJsonHelloWorldUtf8(bool formatted, BufferWriter<IBufferWriter<byte>> output) | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above |
||||||||
| { | ||||||||
| var json = new JsonWriter(output, true, formatted); | ||||||||
|
|
||||||||
| json.WriteObjectStart(); | ||||||||
| json.WriteAttribute("message", "Hello, World!"); | ||||||||
| json.WriteObjectEnd(); | ||||||||
| json.Flush(); | ||||||||
| } | ||||||||
|
|
||||||||
| private static void WriterSystemTextJsonHelloWorldUtf16(bool formatted, ArrayFormatter output) | ||||||||
| private static void WriterSystemTextJsonHelloWorldUtf16(bool formatted, BufferWriter<IBufferWriter<byte>> output) | ||||||||
| { | ||||||||
| var json = new JsonWriter(output, false, formatted); | ||||||||
|
|
||||||||
| json.WriteObjectStart(); | ||||||||
| json.WriteAttribute("message", "Hello, World!"); | ||||||||
| json.WriteObjectEnd(); | ||||||||
| json.Flush(); | ||||||||
| } | ||||||||
|
|
||||||||
| private static void WriterNewtonsoftHelloWorld(bool formatted, TextWriter writer) | ||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.