// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Numerics; using System.Text; namespace EpicGames.Serialization { /// /// Methods for reading VarUInt values /// public static class VarInt { /// /// Read a variable-length unsigned integer. /// /// A variable-length encoding of an unsigned integer /// public static ulong Read(ReadOnlySpan Buffer) { return Read(Buffer, out _); } /// /// Read a variable-length unsigned integer. /// /// A variable-length encoding of an unsigned integer /// The number of bytes consumed from the input /// public static ulong Read(ReadOnlySpan Buffer, out int BytesRead) { BytesRead = (int)Measure(Buffer); ulong Value = (ulong)(Buffer[0] & (0xff >> BytesRead)); for (int i = 1; i < BytesRead; i++) { Value <<= 8; Value |= Buffer[i]; } return Value; } /// /// Measure the length in bytes (1-9) of an encoded variable-length integer. /// /// A variable-length encoding of an(signed or unsigned) integer. /// The number of bytes used to encode the integer, in the range 1-9. public static int Measure(ReadOnlySpan Buffer) { byte b = Buffer[0]; b = (byte)~b; return BitOperations.LeadingZeroCount(b) - 23; } /// /// Measure the number of bytes (1-5) required to encode the 32-bit input. /// /// /// public static int Measure(int Value) { return Measure((uint)Value); } /// /// Measure the number of bytes (1-5) required to encode the 32-bit input. /// /// /// public static int Measure(uint Value) { return BitOperations.Log2(Value) / 7 + 1; } /// /// Measure the number of bytes (1-9) required to encode the 64-bit input. /// /// /// public static int Measure(ulong value) { return Math.Min(BitOperations.Log2(value) / 7 + 1, 9); } /// /// Write a variable-length unsigned integer. /// /// An unsigned integer to encode /// A buffer of at least 9 bytes to write the output to. /// The number of bytes used in the output public static int Write(Span Buffer, long Value) { return Write(Buffer, (ulong)Value); } /// /// Write a variable-length unsigned integer. /// /// An unsigned integer to encode /// A buffer of at least 9 bytes to write the output to. /// The number of bytes used in the output public static int Write(Span Buffer, ulong Value) { int ByteCount = Measure(Value); for (int Idx = 1; Idx < ByteCount; Idx++) { Buffer[ByteCount - Idx] = (byte)Value; Value >>= 8; } Buffer[0] = (byte)((0xff << (9 - (int)ByteCount)) | (byte)Value); return ByteCount; } } }