Files
Ananta-ps/Ananta.SDK/Serialization/UxReader.cs
T

112 lines
2.6 KiB
C#

using System.Buffers.Binary;
using System.Text;
namespace Ananta.SDK.Serialization;
public sealed class UxReader
{
private readonly byte[] _data;
private int _pos;
public UxReader(byte[] data) => _data = data;
public int Position => _pos;
public int Remaining => _data.Length - _pos;
public byte U8() => _data[_pos++];
public bool Bool() => U8() != 0;
public short I16()
{
var v = BinaryPrimitives.ReadInt16LittleEndian(_data.AsSpan(_pos, 2));
_pos += 2;
return v;
}
public ushort U16()
{
var v = BinaryPrimitives.ReadUInt16LittleEndian(_data.AsSpan(_pos, 2));
_pos += 2;
return v;
}
public int I32()
{
var v = BinaryPrimitives.ReadInt32LittleEndian(_data.AsSpan(_pos, 4));
_pos += 4;
return v;
}
public uint U32()
{
var v = BinaryPrimitives.ReadUInt32LittleEndian(_data.AsSpan(_pos, 4));
_pos += 4;
return v;
}
public long I64()
{
var v = BinaryPrimitives.ReadInt64LittleEndian(_data.AsSpan(_pos, 8));
_pos += 8;
return v;
}
public ulong U64()
{
var v = BinaryPrimitives.ReadUInt64LittleEndian(_data.AsSpan(_pos, 8));
_pos += 8;
return v;
}
public float F32()
{
var v = BitConverter.ToSingle(_data, _pos);
_pos += 4;
return v;
}
public double F64()
{
var v = BitConverter.ToDouble(_data, _pos);
_pos += 8;
return v;
}
public int Int7() => Math.Max(0, ReadVarInt() - 1);
public string UxString() => UxStringNullable() ?? string.Empty;
public string? UxStringNullable()
{
var lenPlus = ReadVarInt();
if (lenPlus == 0) return null;
var len = Math.Max(0, lenPlus - 1);
if (len > Remaining) throw new InvalidDataException($"UX string length {len} exceeds remaining {Remaining} bytes.");
var s = Encoding.UTF8.GetString(_data, _pos, len);
_pos += len;
return s;
}
public byte[] Bytes(int count)
{
if (count < 0 || count > Remaining)
throw new InvalidDataException($"UX buffer length {count} exceeds remaining {Remaining} bytes.");
var result = _data.AsSpan(_pos, count).ToArray();
_pos += count;
return result;
}
private int ReadVarInt()
{
var shift = 0;
var result = 0;
while (_pos < _data.Length)
{
var b = _data[_pos++];
result |= (b & 0x7F) << shift;
if ((b & 0x80) == 0) break;
shift += 7;
}
return result;
}
}