using System; using System.Diagnostics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; /// /// Unpacks a BinLinkerAccessor generated file container into individual arrays. /// [DebuggerDisplay($"{{{nameof(Identifier)},nq}}[{{{nameof(Length)},nq}}]")] public readonly ref struct BinLinkerAccessor { /// Backing data object private readonly ReadOnlySpan Data; /// Total count of files available for accessing. public int Length => ReadUInt16LittleEndian(Data[2..]); /// Magic identifier for the file. public string Identifier => new(new[] {(char)Data[0], (char)Data[1]}); /// /// Retrieves a view of the entry at the requested . /// /// Entry to retrieve. public ReadOnlySpan this[int index] => GetEntry(index); private BinLinkerAccessor(ReadOnlySpan data) => Data = data; private ReadOnlySpan GetEntry(int index) { int offset = 4 + (index * sizeof(int)); int end = ReadInt32LittleEndian(Data[(offset + 4)..]); int start = ReadInt32LittleEndian(Data[offset..]); return Data[start..end]; } /// /// Sanity checks the input only in DEBUG builds, and returns a new wrapper. /// /// Data reference /// Expected identifier (debug verification only) public static BinLinkerAccessor Get(ReadOnlySpan data, string identifier) { SanityCheckIdentifier(data, identifier); return new BinLinkerAccessor(data); } [Conditional("DEBUG")] private static void SanityCheckIdentifier(ReadOnlySpan data, string identifier) { Debug.Assert(data.Length > 4); Debug.Assert(identifier[0] == data[0] && identifier[1] == data[1]); } }