From d1953f9ce46d332a281abfad7ab4a5fcaa22199f Mon Sep 17 00:00:00 2001 From: ElektroKill Date: Tue, 21 Dec 2021 21:52:13 +0100 Subject: [PATCH] Allow lazy loading of bunde entry data --- .../Documents/Bundles/BundleEntry.cs | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/dnSpy/dnSpy.Contracts.DnSpy/Documents/Bundles/BundleEntry.cs b/dnSpy/dnSpy.Contracts.DnSpy/Documents/Bundles/BundleEntry.cs index f000b1c363..4f95444363 100644 --- a/dnSpy/dnSpy.Contracts.DnSpy/Documents/Bundles/BundleEntry.cs +++ b/dnSpy/dnSpy.Contracts.DnSpy/Documents/Bundles/BundleEntry.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; +using System.Threading; using dnlib.IO; namespace dnSpy.Contracts.Documents { @@ -8,6 +9,9 @@ namespace dnSpy.Contracts.Documents { /// Represents one entry in a /// public sealed class BundleEntry { + byte[]? data; + DataReader reader; + /// /// Type of the entry /// @@ -31,12 +35,25 @@ public sealed class BundleEntry { /// /// The raw data of the entry. /// - public byte[] Data { get; } + public byte[] Data { + get { + if (data is not null) + return data; + Interlocked.CompareExchange(ref data, reader.ReadRemainingBytes(), null); + return data; + } + } BundleEntry(BundleFileType type, string relativePath, byte[] data) { Type = type; RelativePath = relativePath.Replace('/', '\\'); - Data = data; + this.data = data; + } + + BundleEntry(BundleFileType type, string relativePath, DataReader reader) { + Type = type; + RelativePath = relativePath.Replace('/', '\\'); + this.reader = reader; } internal static IReadOnlyList ReadEntries(DataReader reader, int count, bool allowCompression) { @@ -49,18 +66,16 @@ internal static IReadOnlyList ReadEntries(DataReader reader, int co var type = (BundleFileType)reader.ReadByte(); string path = reader.ReadSerializedString(); - res[i] = new BundleEntry(type, path, ReadEntryData(reader, offset, size, compSize)); + if (compSize == 0) + res[i] = new BundleEntry(type, path, reader.Slice((uint)offset, (uint)size)); + else + res[i] = new BundleEntry(type, path, ReadCompressedEntryData(reader, offset, size, compSize)); } return res; } - static byte[] ReadEntryData(DataReader reader, long offset, long size, long compSize) { - if (compSize == 0) { - reader.Position = (uint)offset; - return reader.ReadBytes((int)size); - } - + static byte[] ReadCompressedEntryData(DataReader reader, long offset, long size, long compSize) { using (var decompressedStream = new MemoryStream((int)size)) { using (var compressedStream = reader.Slice((uint)offset, (uint)compSize).AsStream()) { using (var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress)) {