// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Numerics; 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((ulong)(long)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; } } }