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.
ci / server (push) Failing after 4m10s
ci / client (push) Successful in 17s

This commit is contained in:
Leonid Pershin
2026-08-18 11:11:48 +03:00
parent 84aafb0b69
commit e6739e7912
84 changed files with 5698 additions and 2 deletions
+75
View File
@@ -0,0 +1,75 @@
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;
}
public long ReadInt64()
{
EnsureAvailable(sizeof(long));
var value = BinaryPrimitives.ReadInt64LittleEndian(_buffer[_position..]);
_position += sizeof(long);
return value;
}
public float ReadSingle()
{
EnsureAvailable(sizeof(float));
var value = BinaryPrimitives.ReadSingleLittleEndian(_buffer[_position..]);
_position += sizeof(float);
return value;
}
public string ReadShortString()
{
var byteCount = ReadByte();
EnsureAvailable(byteCount);
var value = Encoding.UTF8.GetString(_buffer.Slice(_position, byteCount));
_position += byteCount;
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.");
}
}
}