using System.Runtime.CompilerServices; namespace VersionedSerialization; public static class ReaderExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint ReadCompressedUInt(this ref T reader) where T : struct, IReader, allows ref struct { var first = reader.ReadPrimitive(); if ((first & 0b10000000) == 0b00000000) return first; if ((first & 0b11000000) == 0b10000000) return (uint)(((first & ~0b10000000) << 8) | reader.ReadPrimitive()); if ((first & 0b11100000) == 0b11000000) return (uint)(((first & ~0b11000000) << 24) | (reader.ReadPrimitive() << 16) | (reader.ReadPrimitive() << 8) | reader.ReadPrimitive()); return first switch { 0b11110000 => reader.ReadPrimitive(), 0b11111110 => uint.MaxValue - 1, 0b11111111 => uint.MaxValue, _ => throw new InvalidDataException("Invalid compressed uint") }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ReadCompressedInt(this ref T reader) where T : struct, IReader, allows ref struct { var value = reader.ReadCompressedUInt(); if (value == uint.MaxValue) return int.MinValue; var isNegative = (value & 0b1) == 1; value >>= 1; return (int)(isNegative ? -(value + 1) : value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong ReadSLEB128(this ref T reader) where T : struct, IReader, allows ref struct { var value = 0uL; var shift = 0; byte current; do { current = reader.ReadPrimitive(); value |= (current & 0x7FuL) << shift; shift += 7; } while ((current & 0x80) != 0); if (64 >= shift && (current & 0x40) != 0) value |= ulong.MaxValue << shift; return value; } }