using System.Collections.Immutable; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using NoisyCowStudios.Bin2Object; using VersionedSerialization; namespace Il2CppInspector.Next; public class BinaryObjectStreamReader : BinaryObjectStream, IReader { public new StructVersion Version { get => _version; set { _version = value; base.Version = _version.AsDouble; } } private StructVersion _version; public virtual int Bits { get; set; } public bool Is32Bit => Bits == 32; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static TTo Cast(in TFrom from) => Unsafe.As(ref Unsafe.AsRef(in from)); [MethodImpl(MethodImplOptions.AggressiveInlining)] private T ReadInternal() where T : unmanaged { var size = Unsafe.SizeOf(); var value = MemoryMarshal.Read(ReadBytes(size)); return value; } public T ReadPrimitive() where T : unmanaged { if (typeof(T) == typeof(sbyte)) return Cast(ReadByte()); if (typeof(T) == typeof(short)) return Cast(ReadInt16()); if (typeof(T) == typeof(int)) return Cast(ReadInt32()); if (typeof(T) == typeof(long)) return Cast(ReadInt64()); if (typeof(T) == typeof(byte)) return Cast(ReadByte()); if (typeof(T) == typeof(ushort)) return Cast(ReadUInt16()); if (typeof(T) == typeof(uint)) return Cast(ReadUInt32()); if (typeof(T) == typeof(ulong)) return Cast(ReadUInt64()); return ReadInternal(); } public ImmutableArray ReadPrimitiveArray(long count) where T : unmanaged { var array = ImmutableArray.CreateBuilder(checked((int)count)); for (long i = 0; i < count; i++) array.Add(ReadPrimitive()); return array.MoveToImmutable(); } public T ReadVersionedObject() where T : IReadable, new() => ReadVersionedObject(Version); public T ReadVersionedObject(in StructVersion version = default) where T : IReadable, new() { var obj = new T(); var a = this; obj.Read(ref a, in version); return obj; } public ImmutableArray ReadVersionedObjectArray(long count) where T : IReadable, new() => ReadVersionedObjectArray(count, Version); public ImmutableArray ReadVersionedObjectArray(long count, in StructVersion version = default) where T : IReadable, new() { var array = ImmutableArray.CreateBuilder(checked((int)count)); for (long i = 0; i < count; i++) array.Add(ReadVersionedObject(in version)); return array.MoveToImmutable(); } public long ReadNInt() => Is32Bit ? ReadPrimitive() : ReadPrimitive(); public ulong ReadNUInt() => Is32Bit ? ReadPrimitive() : ReadPrimitive(); public string ReadString() => ReadNullTerminatedString(); public new ReadOnlySpan ReadBytes(int length) { return base.ReadBytes(length); } public void Align(int alignment = 0) { if (alignment == 0) alignment = Is32Bit ? 4 : 8; var rem = Position % alignment; if (rem != 0) Position += alignment - rem; } public TType ReadPrimitive(long addr) where TType : unmanaged { Position = addr; return ReadPrimitive(); } public ImmutableArray ReadPrimitiveArray(long addr, long count) where TType : unmanaged { Position = addr; return ReadPrimitiveArray(count); } public TType ReadVersionedObject(long addr) where TType : IReadable, new() { Position = addr; return ReadVersionedObject(Version); } public ImmutableArray ReadVersionedObjectArray(long addr, long count) where TType : IReadable, new() { Position = addr; return ReadVersionedObjectArray(count, Version); } public void Skip(int count) { Position += count; } }