in src/StreamJsonRpc/PipeMessageHandler.cs [222:285]
private protected async ValueTask<JsonRpcMessage> DeserializeMessageAsync(int contentLength, Encoding? specificEncoding, Encoding? defaultEncoding, CancellationToken cancellationToken)
{
Requires.Range(contentLength > 0, nameof(contentLength));
Assumes.NotNull(this.Reader);
Assumes.Null(this.deserializationReservedBuffer.Message); // Previous message holds buffers must have been released by now.
Encoding? contentEncoding = specificEncoding ?? defaultEncoding;
// Being async during deserialization increases GC pressure,
// so prefer getting all bytes into a buffer first if the message is a reasonably small size.
if (contentLength >= LargeMessageThreshold && this.Formatter is IJsonRpcAsyncMessageFormatter asyncFormatter)
{
PipeReader slice = this.Reader.ReadSlice(contentLength);
if (contentEncoding is not null && asyncFormatter is IJsonRpcAsyncMessageTextFormatter asyncTextFormatter)
{
return await asyncTextFormatter.DeserializeAsync(slice, contentEncoding, cancellationToken).ConfigureAwait(false);
}
else
{
if (specificEncoding is not null)
{
this.ThrowNoTextEncoder();
}
return await asyncFormatter.DeserializeAsync(slice, cancellationToken).ConfigureAwait(false);
}
}
else
{
ReadResult readResult = await this.ReadAtLeastAsync(contentLength, allowEmpty: false, cancellationToken).ConfigureAwait(false);
ReadOnlySequence<byte> contentBuffer = readResult.Buffer.Slice(0, contentLength);
try
{
JsonRpcMessage message;
if (contentEncoding is not null && this.Formatter is IJsonRpcMessageTextFormatter textFormatter)
{
message = textFormatter.Deserialize(contentBuffer, contentEncoding);
}
else
{
if (specificEncoding is not null)
{
this.ThrowNoTextEncoder();
}
message = this.Formatter.Deserialize(contentBuffer);
}
if (message is IJsonRpcMessageBufferManager bufferedMessage)
{
this.deserializationReservedBuffer = (bufferedMessage, contentBuffer.End);
}
return message;
}
finally
{
if (this.deserializationReservedBuffer.Message is null)
{
// We're now done reading from the pipe's buffer. We can release it now.
this.Reader.AdvanceTo(contentBuffer.End);
}
}
}
}