@@ -29,6 +29,7 @@ public class Bundle
2929 private byte [ ] _rawZipContents = [ ] ;
3030
3131 private readonly ConcurrentDictionary < string , byte [ ] > _cache = new ( ) ;
32+ private byte [ ] _zipCache = [ ] ;
3233 private readonly int _maxCacheSize ;
3334 private int _currentCacheSize ;
3435
@@ -242,8 +243,32 @@ public ZipArchive OpenZipArchive(ZipArchiveMode mode = ZipArchiveMode.Read)
242243 }
243244 else
244245 {
245- Logger . LogDebug ( "Loading bundle from file: {file}" , BundlePath ) ;
246+ if ( mode == ZipArchiveMode . Read )
247+ {
248+ Stream stream ;
249+ if ( _zipCache . Length == 0 )
250+ {
251+ Logger . LogDebug ( "Loading bundle from file: {file}" , BundlePath ) ;
252+ stream = File . OpenRead ( BundlePath ) ;
253+
254+ if ( ReadOnly && stream . Length < _maxCacheSize )
255+ {
256+ Logger . LogDebug ( "Caching bundle with {Size} bytes" , stream . Length ) ;
257+ _zipCache = ReadStream ( stream ) ;
258+ }
259+ }
260+ else
261+ {
262+ Logger . LogDebug ( "Loading bundle from cache with {Size} bytes" , _zipCache . Length ) ;
263+ stream = new MemoryStream ( _zipCache , writable : false ) ;
264+ }
265+
266+ return new ZipArchive ( stream , ZipArchiveMode . Read ) ;
267+ }
246268
269+ _zipCache = Array . Empty < byte > ( ) ;
270+
271+ Logger . LogDebug ( "Loading bundle from file: {file}" , BundlePath ) ;
247272 return ZipFile . Open ( BundlePath , mode ) ;
248273 }
249274 }
@@ -568,9 +593,37 @@ public X509Certificate2 GetCertificate(string certificateHash)
568593 return certificate ;
569594 }
570595
596+ /// <summary>
597+ /// Gets the data of an entry in the bundle as bytes array and caches the entry data if the bundle is Read-only.
598+ /// </summary>
599+ /// <remarks>
600+ /// Protected entries are only resolved with <see cref="ReadSource.Bundle"/>.
601+ /// </remarks>
602+ /// <param name="entryName">The name of the entry to get the bytes for.</param>
603+ /// <param name="readSource">The source from which to read the data.</param>
604+ /// <returns>The entry data as bytes array.</returns>
605+ public byte [ ] GetBytes ( string entryName , ReadSource readSource )
606+ {
607+ Ensure . String . IsNotNullOrEmpty ( entryName . Trim ( ) , nameof ( entryName ) ) ;
608+
609+ Logger . LogInformation ( "Getting file data for entry: {name}" , entryName ) ;
610+
611+ if ( ! _cache . TryGetValue ( entryName , out var data ) )
612+ {
613+ data = ReadStream ( GetStream ( entryName , readSource ) ) ;
614+
615+ _ = CacheEntry ( entryName , data ) ;
616+ }
617+
618+ return data ;
619+ }
620+
571621 /// <summary>
572622 /// Gets a stream for an entry in the bundle and caches the entry data if the bundle is Read-only.
573623 /// </summary>
624+ /// <remarks>
625+ /// Protected entries are only resolved with <see cref="ReadSource.Bundle"/>.
626+ /// </remarks>
574627 /// <param name="entryName">The name of the entry to get the stream for.</param>
575628 /// <param name="readSource">The source from which to read the data.</param>
576629 /// <returns>A stream for the entry.</returns>
@@ -583,7 +636,7 @@ public Stream GetStream(string entryName, ReadSource readSource = ReadSource.Bot
583636 if ( _cache . TryGetValue ( entryName , out var data ) )
584637 {
585638 Logger . LogDebug ( "Reading entry {name} from cache" , entryName ) ;
586- return new MemoryStream ( data ) ;
639+ return new MemoryStream ( data , writable : false ) ;
587640 }
588641 else
589642 {
@@ -621,28 +674,6 @@ public Stream GetStream(string entryName, ReadSource readSource = ReadSource.Bot
621674
622675 return stream ;
623676 }
624-
625- /// <summary>
626- /// Gets the data of an entry in the bundle as bytes array and caches the entry data if the bundle is Read-only.
627- /// </summary>
628- /// <param name="entryName">The name of the entry to get the bytes for.</param>
629- /// <param name="readSource">The source from which to read the data.</param>
630- /// <returns>The entry data as bytes array.</returns>
631- public byte [ ] GetBytes ( string entryName , ReadSource readSource )
632- {
633- Ensure . String . IsNotNullOrEmpty ( entryName . Trim ( ) , nameof ( entryName ) ) ;
634-
635- Logger . LogInformation ( "Getting file data for entry: {name}" , entryName ) ;
636-
637- if ( ! _cache . TryGetValue ( entryName , out var data ) )
638- {
639- data = ReadStream ( GetStream ( entryName , readSource ) ) ;
640-
641- _ = CacheEntry ( entryName , data ) ;
642- }
643-
644- return data ;
645- }
646677
647678 /// <summary>
648679 /// Writes changes to the bundle file.
@@ -780,9 +811,19 @@ private static byte[] ReadStream(Stream stream)
780811 throw new OverflowException ( "Stream length is too big for buffering" ) ;
781812 }
782813
783- MemoryStream ms = new ( ) ;
784- stream . CopyTo ( ms ) ;
785- return ms . ToArray ( ) ;
814+ byte [ ] result ;
815+ if ( stream is MemoryStream memoryStream )
816+ {
817+ result = memoryStream . ToArray ( ) ;
818+ }
819+ else
820+ {
821+ MemoryStream ms = new ( ) ;
822+ stream . CopyTo ( ms ) ;
823+ result = ms . ToArray ( ) ;
824+ }
825+
826+ return result ;
786827 }
787828
788829 /// <summary>
0 commit comments