Skip to content

Commit

Permalink
Address comments related to Transcoding classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
jozkee committed Mar 25, 2020
1 parent 231085d commit 4970a53
Show file tree
Hide file tree
Showing 8 changed files with 20 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static partial class HttpContentJsonExtensions
public static System.Threading.Tasks.Task<object?> ReadFromJsonAsync(this System.Net.Http.HttpContent content, System.Type type, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public static System.Threading.Tasks.Task<T> ReadFromJsonAsync<T>(this System.Net.Http.HttpContent content, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public partial class JsonContent : System.Net.Http.HttpContent
public sealed partial class JsonContent : System.Net.Http.HttpContent
{
internal JsonContent() { }
public System.Type ObjectType { get { throw null; } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace System.Net.Http.Json
{
public partial class JsonContent : System.Net.Http.HttpContent
public sealed partial class JsonContent : System.Net.Http.HttpContent
{
protected override System.Threading.Tasks.Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext? context, System.Threading.CancellationToken cancellationToken) { throw null; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace System.Net.Http.Json
{
public partial class JsonContent : HttpContent
public sealed partial class JsonContent : HttpContent
{
internal const string JsonMediaType = "application/json";
internal const string JsonType = "application";
Expand Down Expand Up @@ -70,6 +70,9 @@ private async Task SerializeToStreamAsyncCore(Stream targetStream, CancellationT
using (TranscodingWriteStream transcodingStream = new TranscodingWriteStream(targetStream, targetEncoding))
{
await JsonSerializer.SerializeAsync(transcodingStream, Value, ObjectType, _jsonSerializerOptions, cancellationToken).ConfigureAwait(false);
// The transcoding streams use Encoders and Decoders that have internal buffers. We need to flush these
// when there is no more data to be written. Stream.FlushAsync isn't suitable since it's
// acceptable to Flush a Stream (multiple times) prior to completion.
await transcodingStream.FinalWriteAsync(cancellationToken).ConfigureAwait(false);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace System.Net.Http.Json
{
public partial class JsonContent
public sealed partial class JsonContent
{
protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken)
=> SerializeToStreamAsyncCore(stream, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal sealed class TranscodingReadStream : Stream
private static readonly int OverflowBufferSize = Encoding.UTF8.GetMaxByteCount(1); // The most number of bytes used to represent a single UTF char

internal const int MaxByteBufferSize = 4096;
internal const int MaxCharBufferSize = 3 * MaxByteBufferSize;
internal const int MaxCharBufferSize = 4096;

private readonly Stream _stream;
private readonly Decoder _decoder;
Expand Down Expand Up @@ -118,7 +118,7 @@ private async Task<int> ReadAsyncCore(ArraySegment<byte> readBuffer, Cancellatio
if (_charBuffer.Count == 0)
{
int bytesRead = await ReadInputChars(cancellationToken).ConfigureAwait(false);
shouldFlushEncoder = bytesRead == 0;
shouldFlushEncoder = bytesRead == 0 && _byteBuffer.Count == 0;
}

bool completed = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,7 @@ private async Task WriteAsyncCore(ArraySegment<byte> bufferSegment, Cancellation

_charsDecoded += charsDecoded;
bufferSegment = bufferSegment.Slice(bytesDecoded);

if (!decoderCompleted)
{
await WriteBufferAsync(cancellationToken).ConfigureAwait(false);
}
await WriteBufferAsync(cancellationToken).ConfigureAwait(false);
}
}

Expand Down Expand Up @@ -142,10 +138,7 @@ protected override void Dispose(bool disposing)

public async Task FinalWriteAsync(CancellationToken cancellationToken)
{
// First write any buffered content
await WriteBufferAsync(cancellationToken).ConfigureAwait(false);

// Now flush the encoder.
// Flush the encoder.
byte[] byteBuffer = ArrayPool<byte>.Shared.Rent(_maxByteBufferSize);
bool encoderCompleted = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

using System.Net.Http.Headers;
using System.Net.Test.Common;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Xunit;

Expand Down Expand Up @@ -160,13 +162,16 @@ await LoopbackServer.CreateClientAndServerAsync(
{
var request = new HttpRequestMessage(HttpMethod.Post, uri);
MediaTypeHeaderValue mediaType = MediaTypeHeaderValue.Parse("application/json; charset=utf-16");
request.Content = JsonContent.Create(Person.Create(), mediaType: mediaType);
// Pass new options to avoid using the Default Web Options that use camelCase.
request.Content = JsonContent.Create(Person.Create(), mediaType: mediaType, options: new JsonSerializerOptions());
await client.SendAsync(request);
}
},
async server => {
HttpRequestData req = await server.HandleRequestAsync();
Assert.Equal("application/json; charset=utf-16", req.GetSingleHeaderValue("Content-Type"));
Person per = JsonSerializer.Deserialize<Person>(Encoding.Unicode.GetString(req.Body));
per.Validate();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ private static async Task WriteAsyncTest(Encoding targetEncoding, string message

var transcodingStream = new TranscodingWriteStream(stream, targetEncoding);
await JsonSerializer.SerializeAsync(transcodingStream, model, model.GetType());
// The transcoding streams use Encoders and Decoders that have internal buffers. We need to flush these
// when there is no more data to be written. Stream.FlushAsync isn't suitable since it's
// acceptable to Flush a Stream (multiple times) prior to completion.
await transcodingStream.FinalWriteAsync(default);
await transcodingStream.FlushAsync();

Expand Down

0 comments on commit 4970a53

Please sign in to comment.