Protocol v8 adds tenths of a °C and precipitation to the clock frame; warmth drains from insulation versus place temperature. Co-authored-by: Cursor <cursoragent@cursor.com>
85 lines
2.5 KiB
C#
85 lines
2.5 KiB
C#
using System.Buffers.Binary;
|
|
using System.Text;
|
|
|
|
namespace HSchool.Protocol;
|
|
|
|
/// <summary>Little-endian cursor over a received frame. Mirror of <see cref="PacketWriter"/>.</summary>
|
|
public ref struct PacketReader(ReadOnlySpan<byte> buffer)
|
|
{
|
|
private readonly ReadOnlySpan<byte> _buffer = buffer;
|
|
private int _position = 0;
|
|
|
|
public readonly int Position => _position;
|
|
|
|
public readonly int Remaining => _buffer.Length - _position;
|
|
|
|
public byte ReadByte()
|
|
{
|
|
EnsureAvailable(sizeof(byte));
|
|
var value = _buffer[_position];
|
|
_position += sizeof(byte);
|
|
return value;
|
|
}
|
|
|
|
public MessageType ReadMessageType() => (MessageType)ReadByte();
|
|
|
|
public ushort ReadUInt16()
|
|
{
|
|
EnsureAvailable(sizeof(ushort));
|
|
var value = BinaryPrimitives.ReadUInt16LittleEndian(_buffer[_position..]);
|
|
_position += sizeof(ushort);
|
|
return value;
|
|
}
|
|
|
|
public uint ReadUInt32()
|
|
{
|
|
EnsureAvailable(sizeof(uint));
|
|
var value = BinaryPrimitives.ReadUInt32LittleEndian(_buffer[_position..]);
|
|
_position += sizeof(uint);
|
|
return value;
|
|
}
|
|
|
|
/// <summary><c>u16</c> byte length, then UTF-8. Empty string is a zero length.</summary>
|
|
public string ReadString()
|
|
{
|
|
var byteCount = ReadUInt16();
|
|
EnsureAvailable(byteCount);
|
|
var value = Encoding.UTF8.GetString(_buffer.Slice(_position, byteCount));
|
|
_position += byteCount;
|
|
return value;
|
|
}
|
|
|
|
public short ReadInt16()
|
|
{
|
|
EnsureAvailable(sizeof(short));
|
|
var value = BinaryPrimitives.ReadInt16LittleEndian(_buffer[_position..]);
|
|
_position += sizeof(short);
|
|
return value;
|
|
}
|
|
|
|
public int ReadInt32()
|
|
{
|
|
EnsureAvailable(sizeof(int));
|
|
var value = BinaryPrimitives.ReadInt32LittleEndian(_buffer[_position..]);
|
|
_position += sizeof(int);
|
|
return value;
|
|
}
|
|
|
|
public long ReadInt64()
|
|
{
|
|
EnsureAvailable(sizeof(long));
|
|
var value = BinaryPrimitives.ReadInt64LittleEndian(_buffer[_position..]);
|
|
_position += sizeof(long);
|
|
return value;
|
|
}
|
|
|
|
private readonly void EnsureAvailable(int bytes)
|
|
{
|
|
if (_position + bytes > _buffer.Length)
|
|
{
|
|
throw new ProtocolException(
|
|
$"Truncated frame: need {bytes} bytes at offset {_position}, only {Remaining} available.");
|
|
}
|
|
}
|
|
}
|