From 9ea4108e8a0bc0a43cdbc982e6bc530cba7b9ea3 Mon Sep 17 00:00:00 2001 From: LukeFZ <17146677+LukeFZ@users.noreply.github.com> Date: Sat, 28 Feb 2026 03:54:02 +0100 Subject: [PATCH] use IndexOf in IndexType tag parsing to handle ParameterIndex and GenericParameterIndex properly --- .../Next/Metadata/IIndexType.cs | 76 +++++++++++-------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/Il2CppInspector.Common/Next/Metadata/IIndexType.cs b/Il2CppInspector.Common/Next/Metadata/IIndexType.cs index 8c65c98..732057f 100644 --- a/Il2CppInspector.Common/Next/Metadata/IIndexType.cs +++ b/Il2CppInspector.Common/Next/Metadata/IIndexType.cs @@ -1,53 +1,67 @@ -using VersionedSerialization; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using VersionedSerialization; namespace Il2CppInspector.Next.Metadata; +file static class Il2CppMetadataIndex +{ + public const int Invalid = -1; + public const char NumberZeroChar = '0'; +} + public interface IIndexType where T : IIndexType, allows ref struct { public static abstract string TagPrefix { get; } - private static string TagSize4 => $"{T.TagPrefix}4"; - private static string TagSize2 => $"{T.TagPrefix}2"; - private static string TagSize1 => $"{T.TagPrefix}1"; - - private static bool HasCustomSize(in StructVersion version) - => version.Tag != null - && (version.Tag.Contains(TagSize2) - || version.Tag.Contains(TagSize1)); - - public static int IndexSize(in StructVersion version = default, bool is32Bit = false) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int GetSizeFromTag(in StructVersion version) { - if (version.Tag != null && HasCustomSize(version)) + // Fallback to the default for unsupported configurations. + if (version < MetadataVersions.V380 || version.Tag == null) { - if (version.Tag.Contains(TagSize2)) - return sizeof(ushort); - - if (version.Tag.Contains(TagSize1)) - return sizeof(byte); + return sizeof(int); } - return sizeof(int); + // Get the position of the size tag in the version tag. + // Bail out if not found. + var sizeTagPosition = version.Tag.IndexOf(T.TagPrefix, StringComparison.Ordinal); + if (sizeTagPosition == -1) + { + return sizeof(int); + } + // Get the number that follows immediately after the size tag, and convert it to the actual size. + var numberChar = version.Tag[sizeTagPosition + T.TagPrefix.Length]; + return numberChar - Il2CppMetadataIndex.NumberZeroChar; } + public static int IndexSize(in StructVersion version = default, bool is32Bit = false) + => GetSizeFromTag(version); + public static int ReadIndex(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct { - if (version.Tag != null && HasCustomSize(version)) - { - if (version.Tag.Contains(TagSize2)) - { - var value = reader.ReadPrimitive(); - return value == ushort.MaxValue ? -1 : value; - } + var size = GetSizeFromTag(in version); - if (version.Tag.Contains(TagSize1)) - { - var value = reader.ReadPrimitive(); - return value == byte.MaxValue ? -1 : value; - } + int index; + if (size == sizeof(int)) + { + index = reader.ReadPrimitive(); + } + else if (size == sizeof(ushort)) + { + var value = reader.ReadPrimitive(); + index = value == ushort.MaxValue ? Il2CppMetadataIndex.Invalid : value; + } + else + { + Debug.Assert(size == sizeof(byte)); + + var value = reader.ReadPrimitive(); + index = value == byte.MaxValue ? Il2CppMetadataIndex.Invalid : value; } - return reader.ReadPrimitive(); + return index; } } \ No newline at end of file