mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-26 08:02:59 +08:00
@@ -2,25 +2,27 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using MQTTnet.Exceptions;
|
using MQTTnet.Exceptions;
|
||||||
using MQTTnet.Internal;
|
using MQTTnet.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace MQTTnet.Formatter
|
namespace MQTTnet.Formatter
|
||||||
{
|
{
|
||||||
public sealed class MqttBufferReader
|
public sealed class MqttBufferReader
|
||||||
{
|
{
|
||||||
byte[] _buffer = EmptyBuffer.Array;
|
byte[] _buffer = EmptyBuffer.Array;
|
||||||
int _maxPosition;
|
|
||||||
int _offset;
|
int _offset;
|
||||||
|
int _position;
|
||||||
|
int _maxPosition;
|
||||||
|
|
||||||
public int BytesLeft => _maxPosition - Position;
|
public int BytesLeft => _maxPosition - _position;
|
||||||
|
|
||||||
public bool EndOfStream => BytesLeft == 0;
|
public bool EndOfStream => BytesLeft == 0;
|
||||||
|
|
||||||
public int Position { get; private set; }
|
public int Position => _position - _offset;
|
||||||
|
|
||||||
public byte[] ReadBinaryData()
|
public byte[] ReadBinaryData()
|
||||||
{
|
{
|
||||||
@@ -34,8 +36,8 @@ namespace MQTTnet.Formatter
|
|||||||
ValidateReceiveBuffer(length);
|
ValidateReceiveBuffer(length);
|
||||||
|
|
||||||
var result = new byte[length];
|
var result = new byte[length];
|
||||||
Array.Copy(_buffer, Position + _offset, result, 0, length);
|
Array.Copy(_buffer, _position, result, 0, length);
|
||||||
Position += length;
|
_position += length;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -43,8 +45,7 @@ namespace MQTTnet.Formatter
|
|||||||
public byte ReadByte()
|
public byte ReadByte()
|
||||||
{
|
{
|
||||||
ValidateReceiveBuffer(1);
|
ValidateReceiveBuffer(1);
|
||||||
|
return _buffer[_position++];
|
||||||
return _buffer[Position++];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ReadFourByteInteger()
|
public uint ReadFourByteInteger()
|
||||||
@@ -52,34 +53,36 @@ namespace MQTTnet.Formatter
|
|||||||
ValidateReceiveBuffer(4);
|
ValidateReceiveBuffer(4);
|
||||||
|
|
||||||
#if NETCOREAPP3_0_OR_GREATER
|
#if NETCOREAPP3_0_OR_GREATER
|
||||||
var value = System.Runtime.InteropServices.MemoryMarshal.Read<uint>(_buffer.AsSpan().Slice(Position));
|
var value = MemoryMarshal.Read<uint>(_buffer.AsSpan(_position));
|
||||||
value = System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(value);
|
if (BitConverter.IsLittleEndian)
|
||||||
|
{
|
||||||
|
value = System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
var byte0 = _buffer[_offset + Position];
|
var byte0 = _buffer[_position];
|
||||||
var byte1 = _buffer[_offset + Position + 1];
|
var byte1 = _buffer[_position + 1];
|
||||||
var byte2 = _buffer[_offset + Position + 2];
|
var byte2 = _buffer[_position + 2];
|
||||||
var byte3 = _buffer[_offset + Position + 3];
|
var byte3 = _buffer[_position + 3];
|
||||||
|
|
||||||
var value = (uint)((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
|
var value = (uint)((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Position += 4;
|
_position += 4;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ReadRemainingData()
|
public byte[] ReadRemainingData()
|
||||||
{
|
{
|
||||||
var bufferLength = _maxPosition - Position - _offset;
|
var bufferLength = BytesLeft;
|
||||||
|
|
||||||
if (bufferLength == 0)
|
if (bufferLength == 0)
|
||||||
{
|
{
|
||||||
return EmptyBuffer.Array;
|
return EmptyBuffer.Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer = new byte[bufferLength];
|
var buffer = new byte[bufferLength];
|
||||||
Array.Copy(_buffer, Position + _offset, buffer, 0, bufferLength);
|
Array.Copy(_buffer, _position, buffer, 0, bufferLength);
|
||||||
|
|
||||||
Position += bufferLength;
|
_position += bufferLength;
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@@ -97,12 +100,12 @@ namespace MQTTnet.Formatter
|
|||||||
|
|
||||||
#if NETCOREAPP3_0_OR_GREATER
|
#if NETCOREAPP3_0_OR_GREATER
|
||||||
// AsSpan() version is slightly faster. Not much but at least a little bit.
|
// AsSpan() version is slightly faster. Not much but at least a little bit.
|
||||||
var result = Encoding.UTF8.GetString(_buffer.AsSpan(_offset + Position, length));
|
var result = Encoding.UTF8.GetString(_buffer.AsSpan(_position, length));
|
||||||
#else
|
#else
|
||||||
var result = Encoding.UTF8.GetString(_buffer, _offset + Position, length);
|
var result = Encoding.UTF8.GetString(_buffer, _position, length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Position += length;
|
_position += length;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,16 +114,19 @@ namespace MQTTnet.Formatter
|
|||||||
ValidateReceiveBuffer(2);
|
ValidateReceiveBuffer(2);
|
||||||
|
|
||||||
#if NETCOREAPP3_0_OR_GREATER
|
#if NETCOREAPP3_0_OR_GREATER
|
||||||
var value = System.Runtime.InteropServices.MemoryMarshal.Read<ushort>(_buffer.AsSpan().Slice(Position));
|
var value = MemoryMarshal.Read<ushort>(_buffer.AsSpan(_position));
|
||||||
value = System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(value);
|
if (BitConverter.IsLittleEndian)
|
||||||
|
{
|
||||||
|
value = System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
var msb = _buffer[_offset + Position];
|
var msb = _buffer[_position];
|
||||||
var lsb = _buffer[_offset + Position + 1];
|
var lsb = _buffer[_position + 1];
|
||||||
|
|
||||||
var value = (ushort)((msb << 8) | lsb);
|
var value = (ushort)((msb << 8) | lsb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Position += 2;
|
_position += 2;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,26 +154,29 @@ namespace MQTTnet.Formatter
|
|||||||
|
|
||||||
public void Seek(int position)
|
public void Seek(int position)
|
||||||
{
|
{
|
||||||
Position = position;
|
_position = _offset + position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBuffer(ArraySegment<byte> buffer)
|
||||||
|
{
|
||||||
|
SetBuffer(buffer.Array, buffer.Offset, buffer.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBuffer(byte[] buffer, int offset, int length)
|
public void SetBuffer(byte[] buffer, int offset, int length)
|
||||||
{
|
{
|
||||||
_buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
|
_buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
|
||||||
_offset = offset;
|
_offset = offset;
|
||||||
|
_position = offset;
|
||||||
Position = 0;
|
_maxPosition = offset + length;
|
||||||
_maxPosition = length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
void ValidateReceiveBuffer(int length)
|
void ValidateReceiveBuffer(int length)
|
||||||
{
|
{
|
||||||
var newPosition = Position + _offset + length;
|
var newPosition = _position + length;
|
||||||
|
|
||||||
if (_maxPosition < newPosition)
|
if (_maxPosition < newPosition)
|
||||||
{
|
{
|
||||||
throw new MqttProtocolViolationException($"Expected at least {Position + length} bytes but there are only {_maxPosition} bytes");
|
throw new MqttProtocolViolationException($"Expected at least {newPosition} bytes but there are only {_maxPosition} bytes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user