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 caller-owned buffer. Little-endian matches the
|
|
/// browser's <c>DataView</c> calls in <c>src/HSchool.Client/src/net/protocol.ts</c>.
|
|
/// </summary>
|
|
public ref struct PacketWriter(Span<byte> buffer)
|
|
{
|
|
private readonly Span<byte> _buffer = buffer;
|
|
private int _position = 0;
|
|
|
|
public readonly int Position => _position;
|
|
|
|
public void WriteByte(byte value)
|
|
{
|
|
EnsureRoom(sizeof(byte));
|
|
_buffer[_position] = value;
|
|
_position += sizeof(byte);
|
|
}
|
|
|
|
public void WriteMessageType(MessageType value) => WriteByte((byte)value);
|
|
|
|
public void WriteUInt16(ushort value)
|
|
{
|
|
EnsureRoom(sizeof(ushort));
|
|
BinaryPrimitives.WriteUInt16LittleEndian(_buffer[_position..], value);
|
|
_position += sizeof(ushort);
|
|
}
|
|
|
|
public void WriteUInt32(uint value)
|
|
{
|
|
EnsureRoom(sizeof(uint));
|
|
BinaryPrimitives.WriteUInt32LittleEndian(_buffer[_position..], value);
|
|
_position += sizeof(uint);
|
|
}
|
|
|
|
/// <summary><c>u16</c> byte length, then UTF-8. Empty string is a zero length.</summary>
|
|
public void WriteString(string value)
|
|
{
|
|
var byteCount = Encoding.UTF8.GetByteCount(value);
|
|
if (byteCount > ushort.MaxValue)
|
|
{
|
|
throw new ProtocolException($"String is {byteCount} bytes; u16 length cannot hold it.");
|
|
}
|
|
|
|
WriteUInt16((ushort)byteCount);
|
|
EnsureRoom(byteCount);
|
|
Encoding.UTF8.GetBytes(value, _buffer[_position..]);
|
|
_position += byteCount;
|
|
}
|
|
|
|
public void WriteInt16(short value)
|
|
{
|
|
EnsureRoom(sizeof(short));
|
|
BinaryPrimitives.WriteInt16LittleEndian(_buffer[_position..], value);
|
|
_position += sizeof(short);
|
|
}
|
|
|
|
public void WriteInt32(int value)
|
|
{
|
|
EnsureRoom(sizeof(int));
|
|
BinaryPrimitives.WriteInt32LittleEndian(_buffer[_position..], value);
|
|
_position += sizeof(int);
|
|
}
|
|
|
|
public void WriteInt64(long value)
|
|
{
|
|
EnsureRoom(sizeof(long));
|
|
BinaryPrimitives.WriteInt64LittleEndian(_buffer[_position..], value);
|
|
_position += sizeof(long);
|
|
}
|
|
|
|
private readonly void EnsureRoom(int bytes)
|
|
{
|
|
if (_position + bytes > _buffer.Length)
|
|
{
|
|
throw new ProtocolException(
|
|
$"Buffer overflow: need {bytes} more bytes at offset {_position}, capacity is {_buffer.Length}.");
|
|
}
|
|
}
|
|
}
|