Update .gitignore to exclude TypeScript build info and add dist directory. Expand README with project overview, technology stack, prerequisites, and instructions for running and testing the application.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
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 readonly ReadOnlySpan<byte> Written => _buffer[.._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);
|
||||
}
|
||||
|
||||
public void WriteInt64(long value)
|
||||
{
|
||||
EnsureRoom(sizeof(long));
|
||||
BinaryPrimitives.WriteInt64LittleEndian(_buffer[_position..], value);
|
||||
_position += sizeof(long);
|
||||
}
|
||||
|
||||
public void WriteSingle(float value)
|
||||
{
|
||||
EnsureRoom(sizeof(float));
|
||||
BinaryPrimitives.WriteSingleLittleEndian(_buffer[_position..], value);
|
||||
_position += sizeof(float);
|
||||
}
|
||||
|
||||
/// <summary>Writes a UTF-8 string prefixed with a single length byte.</summary>
|
||||
public void WriteShortString(string value)
|
||||
{
|
||||
var byteCount = Encoding.UTF8.GetByteCount(value);
|
||||
if (byteCount > ProtocolConstants.MaxPlayerNameBytes)
|
||||
{
|
||||
throw new ProtocolException(
|
||||
$"String is {byteCount} bytes, limit is {ProtocolConstants.MaxPlayerNameBytes}.");
|
||||
}
|
||||
|
||||
WriteByte((byte)byteCount);
|
||||
EnsureRoom(byteCount);
|
||||
Encoding.UTF8.GetBytes(value, _buffer[_position..]);
|
||||
_position += byteCount;
|
||||
}
|
||||
|
||||
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}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user