using System.Buffers.Binary;
namespace Fleet.Core;
/// LEB128 变长整数(无符号),以及 zigzag 有符号映射。
public static class VarInt
{
public const int MaxBytes = 10;
public static ulong ZigZag(long value) => (ulong)((value << 1) ^ (value >> 63));
public static long UnZigZag(ulong value) => (long)(value >> 1) ^ -(long)(value & 1);
public static int Write(Span destination, ulong value)
{
int i = 0;
while (value >= 0x80)
{
destination[i++] = (byte)(value | 0x80);
value >>= 7;
}
destination[i++] = (byte)value;
return i;
}
public static void Write(Stream destination, ulong value)
{
Span buffer = stackalloc byte[MaxBytes];
int n = Write(buffer, value);
destination.Write(buffer[..n]);
}
/// 读取失败(数据被截断或超过 10 字节)时返回 false。
public static bool TryRead(ReadOnlySpan source, out ulong value, out int consumed)
{
value = 0;
consumed = 0;
int shift = 0;
while (consumed < source.Length && consumed < MaxBytes)
{
byte b = source[consumed++];
value |= (ulong)(b & 0x7F) << shift;
if ((b & 0x80) == 0)
{
return true;
}
shift += 7;
}
return false;
}
}