選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

SpanBasedMqttPacketBodyReader.cs 3.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using MQTTnet.Exceptions;
  2. using MQTTnet.Formatter;
  3. using System;
  4. using System.Buffers.Binary;
  5. using System.Text;
  6. namespace MQTTnet.AspNetCore
  7. {
  8. public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
  9. {
  10. private ReadOnlyMemory<byte> _buffer;
  11. private int _offset;
  12. public void SetBuffer(ReadOnlyMemory<byte> buffer)
  13. {
  14. _buffer = buffer;
  15. _offset = 0;
  16. }
  17. public ulong Length => (ulong)_buffer.Length;
  18. public bool EndOfStream => _buffer.Length.Equals(_offset);
  19. public ulong Offset => (ulong)_offset;
  20. public byte ReadByte()
  21. {
  22. return _buffer.Span[_offset++];
  23. }
  24. public byte[] ReadRemainingData()
  25. {
  26. return _buffer.Slice(_offset).ToArray();
  27. }
  28. public byte[] ReadWithLengthPrefix()
  29. {
  30. return ReadSegmentWithLengthPrefix().ToArray();
  31. }
  32. private ReadOnlySpan<byte> ReadSegmentWithLengthPrefix()
  33. {
  34. var span = _buffer.Span;
  35. var length = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(_offset));
  36. var result = span.Slice(_offset+2, length);
  37. _offset += 2 + length;
  38. return result;
  39. }
  40. public unsafe string ReadStringWithLengthPrefix()
  41. {
  42. var buffer = ReadSegmentWithLengthPrefix();
  43. if (buffer.Length == 0)
  44. {
  45. return string.Empty;
  46. }
  47. fixed (byte* bytes = &buffer.GetPinnableReference())
  48. {
  49. var result = Encoding.UTF8.GetString(bytes, buffer.Length);
  50. return result;
  51. }
  52. }
  53. public ushort ReadTwoByteInteger()
  54. {
  55. var result = BinaryPrimitives.ReadUInt16BigEndian(_buffer.Span.Slice(_offset));
  56. _offset += 2;
  57. return result;
  58. }
  59. public uint ReadFourByteInteger()
  60. {
  61. var result = BinaryPrimitives.ReadUInt32BigEndian(_buffer.Span.Slice(_offset));
  62. _offset += 4;
  63. return result;
  64. }
  65. public uint ReadVariableLengthInteger()
  66. {
  67. var multiplier = 1;
  68. var value = 0U;
  69. byte encodedByte;
  70. do
  71. {
  72. encodedByte = ReadByte();
  73. value += (uint)((encodedByte & 127) * multiplier);
  74. if (multiplier > 2097152)
  75. {
  76. throw new MqttProtocolViolationException("Variable length integer is invalid.");
  77. }
  78. multiplier *= 128;
  79. } while ((encodedByte & 128) != 0);
  80. return value;
  81. }
  82. public bool ReadBoolean()
  83. {
  84. var buffer = ReadByte();
  85. if (buffer == 0)
  86. {
  87. return false;
  88. }
  89. if (buffer == 1)
  90. {
  91. return true;
  92. }
  93. throw new MqttProtocolViolationException("Boolean values can be 0 or 1 only.");
  94. }
  95. public void Seek(ulong position)
  96. {
  97. _offset = (int)position;
  98. }
  99. }
  100. }