Last active
May 3, 2022 07:10
-
-
Save ForeverZer0/91770b6027cf549a39cadd06fd751064 to your computer and use it in GitHub Desktop.
Static helper classes for reading/writing Minecraft-compatible VarInt and VarLong values to a Stream or arbitrary array of bytes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
namespace MyNamespace; | |
/// <summary> | |
/// Provides static functions for encoding/decoding variable-length integers represented as a <see cref="int"/>. | |
/// </summary> | |
public class VarInt | |
{ | |
private const int SEGMENT_BITS = 0x7F; | |
private const int CONTINUE_BIT = 0x80; | |
/// <summary> | |
/// The maximum number of bytes that a serialized <see cref="VarInt"/> can encompass. | |
/// </summary> | |
public const int MaxSize = 5; | |
/// <summary> | |
/// Encodes a <see cref="int"/> as a variable-length integer into the specified <paramref name="buffer"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="buffer">A <see cref="Span{T}"/> to receive the encoded value.</param> | |
/// <returns>The number of written into the <paramref name="buffer"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode(int value, Span<byte> buffer) | |
{ | |
var unsigned = Unsafe.As<int, uint>(ref value); | |
var pos = 0; | |
unchecked | |
{ | |
do | |
{ | |
var byteVal = unsigned & SEGMENT_BITS; | |
unsigned >>= 7; | |
if (unsigned != 0) | |
byteVal |= CONTINUE_BIT; | |
buffer[pos++] = (byte) byteVal; | |
} while (unsigned != 0); | |
} | |
return pos; | |
} | |
/// <summary> | |
/// Encodes a <see cref="int"/> as a variable-length integer into the specified <paramref name="buffer"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="buffer">A buffer to receive the encoded value.</param> | |
/// <param name="start">The offset into the <paramref name="buffer"/> to begin writing into.</param> | |
/// <param name="length">The maximum number of bytes that can be written to the <paramref name="buffer"/>.</param> | |
/// <returns>The number of written into the <paramref name="buffer"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode(int value, byte[] buffer, int start, int length) | |
{ | |
var span = new Span<byte>(buffer, start, length); | |
return Encode(value, span); | |
} | |
/// <summary> | |
/// Encodes a <see cref="int"/> as a variable-length integer into the specified <paramref name="stream"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="stream">A <see cref="Stream"/> to receive the encoded value.</param> | |
/// <returns>The number of written into the <paramref name="stream"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode(int value, Stream stream) | |
{ | |
var unsigned = Unsafe.As<int, uint>(ref value); | |
var pos = 0; | |
do | |
{ | |
var byteVal = unsigned & SEGMENT_BITS; | |
unsigned >>= 7; | |
if (unsigned != 0) | |
byteVal |= CONTINUE_BIT; | |
stream.WriteByte((byte) byteVal); | |
pos++; | |
} while (unsigned != 0); | |
return pos; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="int"/> value. | |
/// </summary> | |
/// <param name="buffer">A <see cref="ReadOnlySpan{T}"/> containing the encoded value.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="buffer"/>.</param> | |
/// <returns>The decoded value as a <see cref="int"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Decode(ReadOnlySpan<byte> buffer, out int size) | |
{ | |
size = 0; | |
var value = 0; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = buffer[size++]; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 32) | |
throw new OverflowException("VarInt exceeds 32-bits."); | |
} | |
} | |
return value; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="int"/> value. | |
/// </summary> | |
/// <param name="buffer">A buffer containing the encoded value.</param> | |
/// <param name="start">The index into the <paramref name="buffer"/> to begin reading.</param> | |
/// <param name="length">The maximum number of bytes that can be read from the <paramref name="buffer"/>.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="buffer"/>.</param> | |
/// <returns>The decoded value as a <see cref="int"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Decode(byte[] buffer, int start, int length, out int size) | |
{ | |
var span = new ReadOnlySpan<byte>(buffer, start, length); | |
return Decode(span, out size); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="stream"/> into a <see cref="int"/> value. | |
/// </summary> | |
/// <param name="stream">A <see cref="Stream"/> containing the encoded value.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="stream"/>.</param> | |
/// <returns>The decoded value as a <see cref="int"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Decode(Stream stream, out int size) | |
{ | |
size = 0; | |
var value = 0; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = (byte) stream.ReadByte(); | |
size++; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 32) | |
throw new OverflowException("VarInt exceeds 32-bits."); | |
} | |
} | |
return value; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="int"/> value. | |
/// </summary> | |
/// <param name="buffer">A <see cref="ReadOnlySpan{T}"/> containing the encoded value.</param> | |
/// <returns>The decoded value as a <see cref="int"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Decode(ReadOnlySpan<byte> buffer) | |
{ | |
var size = 0; | |
var value = 0; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = buffer[size++]; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 32) | |
throw new OverflowException("VarInt exceeds 32-bits."); | |
} | |
} | |
return value; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="int"/> value. | |
/// </summary> | |
/// <param name="buffer">A buffer containing the encoded value.</param> | |
/// <param name="start">The index into the <paramref name="buffer"/> to begin reading.</param> | |
/// <param name="length">The maximum number of bytes that can be read from the <paramref name="buffer"/>.</param> | |
/// <returns>The decoded value as a <see cref="int"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Decode(byte[] buffer, int start, int length) | |
{ | |
var span = new ReadOnlySpan<byte>(buffer, start, length); | |
return Decode(span); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="stream"/> into a <see cref="int"/> value. | |
/// </summary> | |
/// <param name="stream">A <see cref="Stream"/> containing the encoded value.</param> | |
/// <returns>The decoded value as a <see cref="int"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Decode(Stream stream) | |
{ | |
var value = 0; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = (byte) stream.ReadByte(); | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 32) | |
throw new OverflowException("VarInt exceeds 32-bits."); | |
} | |
} | |
return value; | |
} | |
/// <summary> | |
/// Encodes a <see cref="int"/> as a variable-length integer into the specified <paramref name="buffer"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="buffer">A <see cref="Span{T}"/> to receive the encoded value.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The number of written into the <paramref name="buffer"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode<TEnum32>(TEnum32 value, Span<byte> buffer) where TEnum32 : unmanaged, Enum | |
{ | |
var unsigned = Unsafe.As<TEnum32, uint>(ref value); | |
var pos = 0; | |
unchecked | |
{ | |
do | |
{ | |
var byteVal = unsigned & SEGMENT_BITS; | |
unsigned >>= 7; | |
if (unsigned != 0) | |
byteVal |= CONTINUE_BIT; | |
buffer[pos++] = (byte) byteVal; | |
} while (unsigned != 0); | |
} | |
return pos; | |
} | |
/// <summary> | |
/// Encodes a <see cref="int"/> as a variable-length integer into the specified <paramref name="buffer"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="buffer">A buffer to receive the encoded value.</param> | |
/// <param name="start">The offset into the <paramref name="buffer"/> to begin writing into.</param> | |
/// <param name="length">The maximum number of bytes that can be written to the <paramref name="buffer"/>.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The number of written into the <paramref name="buffer"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode<TEnum32>(TEnum32 value, byte[] buffer, int start, int length) where TEnum32 : unmanaged, Enum | |
{ | |
var span = new Span<byte>(buffer, start, length); | |
return Encode(value, span); | |
} | |
/// <summary> | |
/// Encodes a <see cref="int"/> as a variable-length integer into the specified <paramref name="stream"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="stream">A <see cref="Stream"/> to receive the encoded value.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The number of written into the <paramref name="stream"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode<TEnum32>(TEnum32 value, Stream stream) where TEnum32 : unmanaged, Enum | |
{ | |
var unsigned = Unsafe.As<TEnum32, uint>(ref value); | |
var pos = 0; | |
do | |
{ | |
var byteVal = unsigned & SEGMENT_BITS; | |
unsigned >>= 7; | |
if (unsigned != 0) | |
byteVal |= CONTINUE_BIT; | |
stream.WriteByte((byte) byteVal); | |
pos++; | |
} while (unsigned != 0); | |
return pos; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="Enum"/> value. | |
/// </summary> | |
/// <param name="buffer">A <see cref="ReadOnlySpan{T}"/> containing the encoded value.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="buffer"/>.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The decoded value as an enumeration type specified by <typeparamref name="TEnum32"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static TEnum32 Decode<TEnum32>(ReadOnlySpan<byte> buffer, out int size) | |
{ | |
size = 0; | |
var value = 0; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = buffer[size++]; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 32) | |
throw new OverflowException("VarInt exceeds 32-bits."); | |
} | |
} | |
return Unsafe.As<int, TEnum32>(ref value); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="Enum"/> value. | |
/// </summary> | |
/// <param name="buffer">A buffer containing the encoded value.</param> | |
/// <param name="start">The index into the <paramref name="buffer"/> to begin reading.</param> | |
/// <param name="length">The maximum number of bytes that can be read from the <paramref name="buffer"/>.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="buffer"/>.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The decoded value as an enumeration type specified by <typeparamref name="TEnum32"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static TEnum32 Decode<TEnum32>(byte[] buffer, int start, int length, out int size) | |
{ | |
var span = new ReadOnlySpan<byte>(buffer, start, length); | |
return Decode<TEnum32>(span, out size); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="stream"/> into a <see cref="Enum"/> value. | |
/// </summary> | |
/// <param name="stream">A <see cref="Stream"/> containing the encoded value.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="stream"/>.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The decoded value as an enumeration type specified by <typeparamref name="TEnum32"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static TEnum32 Decode<TEnum32>(Stream stream, out int size) | |
{ | |
size = 0; | |
var value = 0; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = (byte) stream.ReadByte(); | |
size++; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 32) | |
throw new OverflowException("VarInt exceeds 32-bits."); | |
} | |
} | |
return Unsafe.As<int, TEnum32>(ref value); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="Enum"/> value. | |
/// </summary> | |
/// <param name="buffer">A <see cref="ReadOnlySpan{T}"/> containing the encoded value.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The decoded value as an enumeration type specified by <typeparamref name="TEnum32"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static TEnum32 Decode<TEnum32>(ReadOnlySpan<byte> buffer) | |
{ | |
var size = 0; | |
var value = 0; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = buffer[size++]; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 32) | |
throw new OverflowException("VarInt exceeds 32-bits."); | |
} | |
} | |
return Unsafe.As<int, TEnum32>(ref value); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="Enum"/> value. | |
/// </summary> | |
/// <param name="buffer">A buffer containing the encoded value.</param> | |
/// <param name="start">The index into the <paramref name="buffer"/> to begin reading.</param> | |
/// <param name="length">The maximum number of bytes that can be read from the <paramref name="buffer"/>.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The decoded value as an enumeration type specified by <typeparamref name="TEnum32"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static TEnum32 Decode<TEnum32>(byte[] buffer, int start, int length) | |
{ | |
var span = new ReadOnlySpan<byte>(buffer, start, length); | |
return Decode<TEnum32>(span); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="stream"/> into a <see cref="Enum"/> value. | |
/// </summary> | |
/// <param name="stream">A <see cref="Stream"/> containing the encoded value.</param> | |
/// <typeparam name="TEnum32">An <see cref="Enum"/> type that is backed by a 32-bit integer.</typeparam> | |
/// <returns>The decoded value as an enumeration type specified by <typeparamref name="TEnum32"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 32-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static TEnum32 Decode<TEnum32>(Stream stream) | |
{ | |
var value = 0; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = (byte) stream.ReadByte(); | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 32) | |
throw new OverflowException("VarInt exceeds 32-bits."); | |
} | |
} | |
return Unsafe.As<int, TEnum32>(ref value); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
namespace MyNamespace; | |
/// <summary> | |
/// Provides static functions for encoding/decoding variable-length integers represented as a <see cref="long"/>. | |
/// </summary> | |
public class VarLong | |
{ | |
private const uint SEGMENT_BITS = 0x7F; | |
private const uint CONTINUE_BIT = 0x80; | |
/// <summary> | |
/// The maximum number of bytes that a serialized <see cref="VarLong"/> can encompass. | |
/// </summary> | |
public const int MaxSize = 10; | |
/// <summary> | |
/// Encodes a <see cref="long"/> as a variable-length integer into the specified <paramref name="buffer"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="buffer">A <see cref="Span{T}"/> to receive the encoded value.</param> | |
/// <returns>The number of written into the <paramref name="buffer"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode(long value, Span<byte> buffer) | |
{ | |
var unsigned = Unsafe.As<long, ulong>(ref value); | |
var pos = 0; | |
do | |
{ | |
var byteVal = unsigned & SEGMENT_BITS; | |
unsigned >>= 7; | |
if (unsigned != 0) | |
byteVal |= CONTINUE_BIT; | |
buffer[pos++] = (byte) byteVal; | |
} while (unsigned != 0); | |
return pos; | |
} | |
/// <summary> | |
/// Encodes a <see cref="long"/> as a variable-length integer into the specified <paramref name="buffer"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="buffer">A buffer to receive the encoded value.</param> | |
/// <param name="start">The offset into the <paramref name="buffer"/> to begin writing into.</param> | |
/// <param name="length">The maximum number of bytes that can be written to the <paramref name="buffer"/>.</param> | |
/// <returns>The number of written into the <paramref name="buffer"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode(long value, byte[] buffer, int start, int length) | |
{ | |
var span = new Span<byte>(buffer, start, length); | |
return Encode(value, span); | |
} | |
/// <summary> | |
/// Encodes a <see cref="long"/> as a variable-length integer into the specified <paramref name="stream"/>. | |
/// </summary> | |
/// <param name="value">The value to encode.</param> | |
/// <param name="stream">A <see cref="Stream"/> to receive the encoded value.</param> | |
/// <returns>The number of written into the <paramref name="stream"/>.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static int Encode(long value, Stream stream) | |
{ | |
var unsigned = Unsafe.As<long, ulong>(ref value); | |
var pos = 0; | |
do | |
{ | |
var byteVal = unsigned & SEGMENT_BITS; | |
unsigned >>= 7; | |
if (unsigned != 0) | |
byteVal |= CONTINUE_BIT; | |
stream.WriteByte((byte) byteVal); | |
pos++; | |
} while (unsigned != 0); | |
return pos; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="long"/> value. | |
/// </summary> | |
/// <param name="buffer">A <see cref="ReadOnlySpan{T}"/> containing the encoded value.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="buffer"/>.</param> | |
/// <returns>The decoded value as a <see cref="long"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 64-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static long Decode(ReadOnlySpan<byte> buffer, out int size) | |
{ | |
size = 0; | |
var value = 0L; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = buffer[size++]; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 64) | |
throw new OverflowException("VarLong exceeds 64-bits."); | |
} | |
} | |
return value; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="long"/> value. | |
/// </summary> | |
/// <param name="buffer">A buffer containing the encoded value.</param> | |
/// <param name="start">The index into the <paramref name="buffer"/> to begin reading.</param> | |
/// <param name="length">The maximum number of bytes that can be read from the <paramref name="buffer"/>.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="buffer"/>.</param> | |
/// <returns>The decoded value as a <see cref="long"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 64-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static long Decode(byte[] buffer, int start, int length, out int size) | |
{ | |
var span = new ReadOnlySpan<byte>(buffer, start, length); | |
return Decode(span, out size); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="stream"/> into a <see cref="long"/> value. | |
/// </summary> | |
/// <param name="stream">A <see cref="Stream"/> containing the encoded value.</param> | |
/// <param name="size">The number of bytes read from the <paramref name="stream"/>.</param> | |
/// <returns>The decoded value as a <see cref="long"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 64-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static long Decode(Stream stream, out int size) | |
{ | |
size = 0; | |
var value = 0L; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = (byte) stream.ReadByte(); | |
size++; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 64) | |
throw new OverflowException("VarLong exceeds 64-bits."); | |
} | |
} | |
return value; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="long"/> value. | |
/// </summary> | |
/// <param name="buffer">A <see cref="ReadOnlySpan{T}"/> containing the encoded value.</param> | |
/// <returns>The decoded value as a <see cref="long"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 64-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static long Decode(ReadOnlySpan<byte> buffer) | |
{ | |
var size = 0; | |
var value = 0L; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = buffer[size++]; | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 64) | |
throw new OverflowException("VarLong exceeds 64-bits."); | |
} | |
} | |
return value; | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="buffer"/> into a <see cref="long"/> value. | |
/// </summary> | |
/// <param name="buffer">A buffer containing the encoded value.</param> | |
/// <param name="start">The index into the <paramref name="buffer"/> to begin reading.</param> | |
/// <param name="length">The maximum number of bytes that can be read from the <paramref name="buffer"/>.</param> | |
/// <returns>The decoded value as a <see cref="long"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 64-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static long Decode(byte[] buffer, int start, int length) | |
{ | |
var span = new ReadOnlySpan<byte>(buffer, start, length); | |
return Decode(span); | |
} | |
/// <summary> | |
/// Decodes a variable-length integer from the specified <paramref name="stream"/> into a <see cref="long"/> value. | |
/// </summary> | |
/// <param name="stream">A <see cref="Stream"/> containing the encoded value.</param> | |
/// <returns>The decoded value as a <see cref="long"/>.</returns> | |
/// <exception cref="OverflowException">The value exceeds 64-bits.</exception> | |
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] | |
public static long Decode(Stream stream) | |
{ | |
var value = 0L; | |
var position = 0; | |
unchecked | |
{ | |
while (true) | |
{ | |
var currentByte = (byte) stream.ReadByte(); | |
value |= (currentByte & SEGMENT_BITS) << position; | |
if ((currentByte & CONTINUE_BIT) == 0) | |
break; | |
position += 7; | |
if (position >= 64) | |
throw new OverflowException("VarLong exceeds 64-bits."); | |
} | |
} | |
return value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment