Switching to new base64 APIs (#1127)
This commit is contained in:
parent
945710907b
commit
379160707f
|
|
@ -9,8 +9,8 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||||
public class MessageParserBenchmark
|
public class MessageParserBenchmark
|
||||||
{
|
{
|
||||||
private static readonly Random Random = new Random();
|
private static readonly Random Random = new Random();
|
||||||
private ReadOnlyMemory<byte> _binaryInput;
|
private byte[] _binaryInput;
|
||||||
private ReadOnlyMemory<byte> _textInput;
|
private byte[] _textInput;
|
||||||
|
|
||||||
[Params(32, 64)]
|
[Params(32, 64)]
|
||||||
public int ChunkSize { get; set; }
|
public int ChunkSize { get; set; }
|
||||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void SingleBinaryMessage()
|
public void SingleBinaryMessage()
|
||||||
{
|
{
|
||||||
var buffer = _binaryInput;
|
ReadOnlySpan<byte> buffer = _binaryInput;
|
||||||
if (!BinaryMessageParser.TryParseMessage(ref buffer, out _))
|
if (!BinaryMessageParser.TryParseMessage(ref buffer, out _))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Failed to parse");
|
throw new InvalidOperationException("Failed to parse");
|
||||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void SingleTextMessage()
|
public void SingleTextMessage()
|
||||||
{
|
{
|
||||||
var buffer = _textInput;
|
ReadOnlySpan<byte> buffer = _textInput;
|
||||||
if (!TextMessageParser.TryParseMessage(ref buffer, out _))
|
if (!TextMessageParser.TryParseMessage(ref buffer, out _))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Failed to parse");
|
throw new InvalidOperationException("Failed to parse");
|
||||||
|
|
|
||||||
|
|
@ -2,27 +2,37 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Buffers.Text;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
||||||
{
|
{
|
||||||
public class Base64Encoder : IDataEncoder
|
public class Base64Encoder : IDataEncoder
|
||||||
{
|
{
|
||||||
public byte[] Decode(byte[] payload)
|
public ReadOnlySpan<byte> Decode(byte[] payload)
|
||||||
{
|
{
|
||||||
var buffer = new ReadOnlyMemory<byte>(payload);
|
ReadOnlySpan<byte> buffer = payload;
|
||||||
LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out var message);
|
LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out var message);
|
||||||
|
|
||||||
return Convert.FromBase64String(Encoding.UTF8.GetString(message.ToArray()));
|
Span<byte> decoded = new byte[Base64.GetMaxDecodedFromUtf8Length(message.Length)];
|
||||||
|
var status = Base64.DecodeFromUtf8(message, decoded, out _, out var written);
|
||||||
|
Debug.Assert(status == OperationStatus.Done);
|
||||||
|
|
||||||
|
return decoded.Slice(0, written);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Encode(byte[] payload)
|
public byte[] Encode(byte[] payload)
|
||||||
{
|
{
|
||||||
var buffer = Encoding.UTF8.GetBytes(Convert.ToBase64String(payload));
|
Span<byte> buffer = new byte[Base64.GetMaxEncodedToUtf8Length(payload.Length)];
|
||||||
|
|
||||||
|
var status = Base64.EncodeToUtf8(payload, buffer, out _, out var written);
|
||||||
|
Debug.Assert(status == OperationStatus.Done);
|
||||||
|
|
||||||
using (var stream = new MemoryStream())
|
using (var stream = new MemoryStream())
|
||||||
{
|
{
|
||||||
LengthPrefixedTextMessageWriter.WriteMessage(buffer, stream);
|
LengthPrefixedTextMessageWriter.WriteMessage(buffer.Slice(0, written), stream);
|
||||||
return stream.ToArray();
|
return stream.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
||||||
{
|
{
|
||||||
public interface IDataEncoder
|
public interface IDataEncoder
|
||||||
{
|
{
|
||||||
byte[] Encode(byte[] payload);
|
byte[] Encode(byte[] payload);
|
||||||
byte[] Decode(byte[] payload);
|
ReadOnlySpan<byte> Decode(byte[] payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,18 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
||||||
/// Attempts to parse a message from the buffer. Returns 'false' if there is not enough data to complete a message. Throws an
|
/// Attempts to parse a message from the buffer. Returns 'false' if there is not enough data to complete a message. Throws an
|
||||||
/// exception if there is a format error in the provided data.
|
/// exception if there is a format error in the provided data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool TryParseMessage(ref ReadOnlyMemory<byte> buffer, out ReadOnlyMemory<byte> payload)
|
public static bool TryParseMessage(ref ReadOnlySpan<byte> buffer, out ReadOnlySpan<byte> payload)
|
||||||
{
|
{
|
||||||
payload = default(ReadOnlyMemory<byte>);
|
payload = default;
|
||||||
|
|
||||||
if (!TryReadLength(buffer.Span, out var index, out var length))
|
if (!TryReadLength(buffer, out var index, out var length))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var remaining = buffer.Slice(index);
|
var remaining = buffer.Slice(index);
|
||||||
|
|
||||||
if (!TryReadDelimiter(remaining.Span, LengthPrefixedTextMessageWriter.FieldDelimiter, "length"))
|
if (!TryReadDelimiter(remaining, LengthPrefixedTextMessageWriter.FieldDelimiter, "length"))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
||||||
|
|
||||||
remaining = remaining.Slice(length);
|
remaining = remaining.Slice(length);
|
||||||
|
|
||||||
if (!TryReadDelimiter(remaining.Span, LengthPrefixedTextMessageWriter.MessageDelimiter, "payload"))
|
if (!TryReadDelimiter(remaining, LengthPrefixedTextMessageWriter.MessageDelimiter, "payload"))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
|
||||||
{
|
{
|
||||||
public class PassThroughEncoder : IDataEncoder
|
public class PassThroughEncoder : IDataEncoder
|
||||||
{
|
{
|
||||||
public byte[] Decode(byte[] payload)
|
public ReadOnlySpan<byte> Decode(byte[] payload)
|
||||||
{
|
{
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Formatters
|
||||||
private static int[] _numBitsToShift = new[] { 0, 7, 14, 21, 28 };
|
private static int[] _numBitsToShift = new[] { 0, 7, 14, 21, 28 };
|
||||||
private const int MaxLengthPrefixSize = 5;
|
private const int MaxLengthPrefixSize = 5;
|
||||||
|
|
||||||
public static bool TryParseMessage(ref ReadOnlyMemory<byte> buffer, out ReadOnlyMemory<byte> payload)
|
public static bool TryParseMessage(ref ReadOnlySpan<byte> buffer, out ReadOnlySpan<byte> payload)
|
||||||
{
|
{
|
||||||
payload = default;
|
payload = default;
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Formatters
|
||||||
var length = 0U;
|
var length = 0U;
|
||||||
var numBytes = 0;
|
var numBytes = 0;
|
||||||
|
|
||||||
var lengthPrefixBuffer = buffer.Span.Slice(0, Math.Min(MaxLengthPrefixSize, buffer.Length));
|
var lengthPrefixBuffer = buffer.Slice(0, Math.Min(MaxLengthPrefixSize, buffer.Length));
|
||||||
byte byteRead;
|
byte byteRead;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Formatters
|
||||||
{
|
{
|
||||||
public static class TextMessageParser
|
public static class TextMessageParser
|
||||||
{
|
{
|
||||||
public static bool TryParseMessage(ref ReadOnlyMemory<byte> buffer, out ReadOnlyMemory<byte> payload)
|
public static bool TryParseMessage(ref ReadOnlySpan<byte> buffer, out ReadOnlySpan<byte> payload)
|
||||||
{
|
{
|
||||||
payload = default;
|
payload = default;
|
||||||
|
|
||||||
var index = buffer.Span.IndexOf(TextMessageFormatter.RecordSeparator);
|
var index = buffer.IndexOf(TextMessageFormatter.RecordSeparator);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
|
|
||||||
ProtocolType Type { get; }
|
ProtocolType Type { get; }
|
||||||
|
|
||||||
bool TryParseMessages(ReadOnlyMemory<byte> input, IInvocationBinder binder, out IList<HubMessage> messages);
|
bool TryParseMessages(ReadOnlySpan<byte> input, IInvocationBinder binder, out IList<HubMessage> messages);
|
||||||
|
|
||||||
void WriteMessage(HubMessage message, Stream output);
|
void WriteMessage(HubMessage message, Stream output);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
|
|
||||||
public ProtocolType Type => ProtocolType.Text;
|
public ProtocolType Type => ProtocolType.Text;
|
||||||
|
|
||||||
public bool TryParseMessages(ReadOnlyMemory<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
public bool TryParseMessages(ReadOnlySpan<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
||||||
{
|
{
|
||||||
messages = new List<HubMessage>();
|
messages = new List<HubMessage>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
_serializationContext = serializationContext;
|
_serializationContext = serializationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryParseMessages(ReadOnlyMemory<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
public bool TryParseMessages(ReadOnlySpan<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
||||||
{
|
{
|
||||||
messages = new List<HubMessage>();
|
messages = new List<HubMessage>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryParseMessage(ReadOnlyMemory<byte> input, out NegotiationMessage negotiationMessage)
|
public static bool TryParseMessage(ReadOnlySpan<byte> input, out NegotiationMessage negotiationMessage)
|
||||||
{
|
{
|
||||||
if (!TextMessageParser.TryParseMessage(ref input, out var payload))
|
if (!TextMessageParser.TryParseMessage(ref input, out var payload))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
||||||
|
|
||||||
public ProtocolType Type => ProtocolType.Binary;
|
public ProtocolType Type => ProtocolType.Binary;
|
||||||
|
|
||||||
public bool TryParseMessages(ReadOnlyMemory<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
public bool TryParseMessages(ReadOnlySpan<byte> input, IInvocationBinder binder, out IList<HubMessage> messages)
|
||||||
{
|
{
|
||||||
messages = new List<HubMessage>();
|
messages = new List<HubMessage>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Encoders
|
||||||
[InlineData("12:Hello, World;", "Hello, World")]
|
[InlineData("12:Hello, World;", "Hello, World")]
|
||||||
public void ReadTextMessage(string encoded, string payload)
|
public void ReadTextMessage(string encoded, string payload)
|
||||||
{
|
{
|
||||||
ReadOnlyMemory<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
ReadOnlySpan<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
||||||
|
|
||||||
Assert.True(LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out var message));
|
Assert.True(LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out var message));
|
||||||
Assert.Equal(0, buffer.Length);
|
Assert.Equal(0, buffer.Length);
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Encoders
|
||||||
public void ReadMultipleMessages()
|
public void ReadMultipleMessages()
|
||||||
{
|
{
|
||||||
const string encoded = "0:;14:Hello,\r\nWorld!;";
|
const string encoded = "0:;14:Hello,\r\nWorld!;";
|
||||||
ReadOnlyMemory<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
ReadOnlySpan<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
||||||
|
|
||||||
var messages = new List<byte[]>();
|
var messages = new List<byte[]>();
|
||||||
while (LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out var message))
|
while (LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out var message))
|
||||||
|
|
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Encoders
|
||||||
[InlineData("5:ABCDE")]
|
[InlineData("5:ABCDE")]
|
||||||
public void ReadIncompleteMessages(string encoded)
|
public void ReadIncompleteMessages(string encoded)
|
||||||
{
|
{
|
||||||
ReadOnlyMemory<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
ReadOnlySpan<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
||||||
Assert.False(LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _));
|
Assert.False(LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,9 +66,9 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Encoders
|
||||||
[InlineData("5:ABCDEF", "Missing delimiter ';' after payload")]
|
[InlineData("5:ABCDEF", "Missing delimiter ';' after payload")]
|
||||||
public void ReadInvalidMessages(string encoded, string expectedMessage)
|
public void ReadInvalidMessages(string encoded, string expectedMessage)
|
||||||
{
|
{
|
||||||
ReadOnlyMemory<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
|
||||||
var ex = Assert.Throws<FormatException>(() =>
|
var ex = Assert.Throws<FormatException>(() =>
|
||||||
{
|
{
|
||||||
|
ReadOnlySpan<byte> buffer = Encoding.UTF8.GetBytes(encoded);
|
||||||
LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _);
|
LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _);
|
||||||
});
|
});
|
||||||
Assert.Equal(expectedMessage, ex.Message);
|
Assert.Equal(expectedMessage, ex.Message);
|
||||||
|
|
@ -77,11 +77,11 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Encoders
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ReadInvalidEncodedMessage()
|
public void ReadInvalidEncodedMessage()
|
||||||
{
|
{
|
||||||
// Invalid because first character is a UTF-8 "continuation" character
|
|
||||||
// We need to include the ':' so that
|
|
||||||
ReadOnlyMemory<byte> buffer = new byte[] { 0x48, 0x65, 0x80, 0x6C, 0x6F, (byte)':' };
|
|
||||||
var ex = Assert.Throws<FormatException>(() =>
|
var ex = Assert.Throws<FormatException>(() =>
|
||||||
{
|
{
|
||||||
|
// Invalid because first character is a UTF-8 "continuation" character
|
||||||
|
// We need to include the ':' so that
|
||||||
|
ReadOnlySpan<byte> buffer = new byte[] { 0x48, 0x65, 0x80, 0x6C, 0x6F, (byte)':' };
|
||||||
LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _);
|
LengthPrefixedTextMessageParser.TryParseMessage(ref buffer, out _);
|
||||||
});
|
});
|
||||||
Assert.Equal("Invalid length: 'He<48>lo'", ex.Message);
|
Assert.Equal("Invalid length: 'He<48>lo'", ex.Message);
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests.Internal.Formatters
|
||||||
using (var ms = new MemoryStream())
|
using (var ms = new MemoryStream())
|
||||||
{
|
{
|
||||||
BinaryMessageFormatter.WriteMessage(payload, ms);
|
BinaryMessageFormatter.WriteMessage(payload, ms);
|
||||||
var buffer = new ReadOnlyMemory<byte>(ms.ToArray());
|
var buffer = new ReadOnlySpan<byte>(ms.ToArray());
|
||||||
Assert.True(BinaryMessageParser.TryParseMessage(ref buffer, out var roundtripped));
|
Assert.True(BinaryMessageParser.TryParseMessage(ref buffer, out var roundtripped));
|
||||||
Assert.Equal(payload, roundtripped.ToArray());
|
Assert.Equal(payload, roundtripped.ToArray());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
[InlineData(new byte[] { 0x0B, 0x41, 0x0A, 0x52, 0x0D, 0x43, 0x0D, 0x0A, 0x3B, 0x44, 0x45, 0x46 }, "A\nR\rC\r\n;DEF")]
|
[InlineData(new byte[] { 0x0B, 0x41, 0x0A, 0x52, 0x0D, 0x43, 0x0D, 0x0A, 0x3B, 0x44, 0x45, 0x46 }, "A\nR\rC\r\n;DEF")]
|
||||||
public void ReadMessage(byte[] encoded, string payload)
|
public void ReadMessage(byte[] encoded, string payload)
|
||||||
{
|
{
|
||||||
ReadOnlyMemory<byte> span = encoded;
|
ReadOnlySpan<byte> span = encoded;
|
||||||
Assert.True(BinaryMessageParser.TryParseMessage(ref span, out var message));
|
Assert.True(BinaryMessageParser.TryParseMessage(ref span, out var message));
|
||||||
Assert.Equal(0, span.Length);
|
Assert.Equal(0, span.Length);
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
})]
|
})]
|
||||||
public void ReadBinaryMessage(byte[] encoded, byte[] payload)
|
public void ReadBinaryMessage(byte[] encoded, byte[] payload)
|
||||||
{
|
{
|
||||||
ReadOnlyMemory<byte> span = encoded;
|
ReadOnlySpan< byte> span = encoded;
|
||||||
Assert.True(BinaryMessageParser.TryParseMessage(ref span, out var message));
|
Assert.True(BinaryMessageParser.TryParseMessage(ref span, out var message));
|
||||||
Assert.Equal(0, span.Length);
|
Assert.Equal(0, span.Length);
|
||||||
Assert.Equal(payload, message.ToArray());
|
Assert.Equal(payload, message.ToArray());
|
||||||
|
|
@ -64,8 +64,11 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
[InlineData(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF })]
|
[InlineData(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF })]
|
||||||
public void BinaryMessageParserThrowsForMessagesOver2GB(byte[] payload)
|
public void BinaryMessageParserThrowsForMessagesOver2GB(byte[] payload)
|
||||||
{
|
{
|
||||||
var buffer = new ReadOnlyMemory<byte>(payload);
|
var ex = Assert.Throws<FormatException>(() =>
|
||||||
var ex = Assert.Throws<FormatException>(() => BinaryMessageParser.TryParseMessage(ref buffer, out var message));
|
{
|
||||||
|
var buffer = new ReadOnlySpan<byte>(payload);
|
||||||
|
BinaryMessageParser.TryParseMessage(ref buffer, out var message);
|
||||||
|
});
|
||||||
Assert.Equal("Messages over 2GB in size are not supported.", ex.Message);
|
Assert.Equal("Messages over 2GB in size are not supported.", ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +79,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
[InlineData(new byte[] { 0x80 })] // size is cut
|
[InlineData(new byte[] { 0x80 })] // size is cut
|
||||||
public void BinaryMessageParserReturnsFalseForPartialPayloads(byte[] payload)
|
public void BinaryMessageParserReturnsFalseForPartialPayloads(byte[] payload)
|
||||||
{
|
{
|
||||||
var buffer = new ReadOnlyMemory<byte>(payload);
|
var buffer = new ReadOnlySpan<byte>(payload);
|
||||||
Assert.False(BinaryMessageParser.TryParseMessage(ref buffer, out var message));
|
Assert.False(BinaryMessageParser.TryParseMessage(ref buffer, out var message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,8 +93,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
/* length: */ 0x0E,
|
/* length: */ 0x0E,
|
||||||
/* body: */ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x0D, 0x0A, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21,
|
/* body: */ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x0D, 0x0A, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21,
|
||||||
};
|
};
|
||||||
ReadOnlyMemory<byte> buffer = encoded;
|
|
||||||
|
|
||||||
|
ReadOnlySpan<byte> buffer = encoded;
|
||||||
var messages = new List<byte[]>();
|
var messages = new List<byte[]>();
|
||||||
while (BinaryMessageParser.TryParseMessage(ref buffer, out var message))
|
while (BinaryMessageParser.TryParseMessage(ref buffer, out var message))
|
||||||
{
|
{
|
||||||
|
|
@ -110,7 +113,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
[InlineData(new byte[] { 0x09, 0x00, 0x00 })] // Not enough data for payload
|
[InlineData(new byte[] { 0x09, 0x00, 0x00 })] // Not enough data for payload
|
||||||
public void ReadIncompleteMessages(byte[] encoded)
|
public void ReadIncompleteMessages(byte[] encoded)
|
||||||
{
|
{
|
||||||
ReadOnlyMemory<byte> buffer = encoded;
|
ReadOnlySpan<byte> buffer = encoded;
|
||||||
Assert.False(BinaryMessageParser.TryParseMessage(ref buffer, out var message));
|
Assert.False(BinaryMessageParser.TryParseMessage(ref buffer, out var message));
|
||||||
Assert.Equal(encoded.Length, buffer.Length);
|
Assert.Equal(encoded.Length, buffer.Length);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ReadMessage()
|
public void ReadMessage()
|
||||||
{
|
{
|
||||||
var message = new ReadOnlyMemory<byte>(Encoding.UTF8.GetBytes("ABC\u001e"));
|
var message = new ReadOnlySpan<byte>(Encoding.UTF8.GetBytes("ABC\u001e"));
|
||||||
|
|
||||||
Assert.True(TextMessageParser.TryParseMessage(ref message, out var payload));
|
Assert.True(TextMessageParser.TryParseMessage(ref message, out var payload));
|
||||||
Assert.Equal("ABC", Encoding.UTF8.GetString(payload.ToArray()));
|
Assert.Equal("ABC", Encoding.UTF8.GetString(payload.ToArray()));
|
||||||
|
|
@ -23,14 +23,14 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TryReadingIncompleteMessage()
|
public void TryReadingIncompleteMessage()
|
||||||
{
|
{
|
||||||
var message = new ReadOnlyMemory<byte>(Encoding.UTF8.GetBytes("ABC"));
|
var message = new ReadOnlySpan<byte>(Encoding.UTF8.GetBytes("ABC"));
|
||||||
Assert.False(TextMessageParser.TryParseMessage(ref message, out var payload));
|
Assert.False(TextMessageParser.TryParseMessage(ref message, out var payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TryReadingMultipleMessages()
|
public void TryReadingMultipleMessages()
|
||||||
{
|
{
|
||||||
var message = new ReadOnlyMemory<byte>(Encoding.UTF8.GetBytes("ABC\u001eXYZ\u001e"));
|
var message = new ReadOnlySpan<byte>(Encoding.UTF8.GetBytes("ABC\u001eXYZ\u001e"));
|
||||||
Assert.True(TextMessageParser.TryParseMessage(ref message, out var payload));
|
Assert.True(TextMessageParser.TryParseMessage(ref message, out var payload));
|
||||||
Assert.Equal("ABC", Encoding.UTF8.GetString(payload.ToArray()));
|
Assert.Equal("ABC", Encoding.UTF8.GetString(payload.ToArray()));
|
||||||
Assert.True(TextMessageParser.TryParseMessage(ref message, out payload));
|
Assert.True(TextMessageParser.TryParseMessage(ref message, out payload));
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Formatters
|
||||||
[Fact]
|
[Fact]
|
||||||
public void IncompleteTrailingMessage()
|
public void IncompleteTrailingMessage()
|
||||||
{
|
{
|
||||||
var message = new ReadOnlyMemory<byte>(Encoding.UTF8.GetBytes("ABC\u001eXYZ\u001e123"));
|
var message = new ReadOnlySpan<byte>(Encoding.UTF8.GetBytes("ABC\u001eXYZ\u001e123"));
|
||||||
Assert.True(TextMessageParser.TryParseMessage(ref message, out var payload));
|
Assert.True(TextMessageParser.TryParseMessage(ref message, out var payload));
|
||||||
Assert.Equal("ABC", Encoding.UTF8.GetString(payload.ToArray()));
|
Assert.Equal("ABC", Encoding.UTF8.GetString(payload.ToArray()));
|
||||||
Assert.True(TextMessageParser.TryParseMessage(ref message, out payload));
|
Assert.True(TextMessageParser.TryParseMessage(ref message, out payload));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue