55using UnityAsset . NET . Files . BundleFiles ;
66using UnityAsset . NET . Files . SerializedFiles ;
77using UnityAsset . NET . IO ;
8+ using StreamReader = UnityAsset . NET . IO . StreamReader ;
89
910namespace UnityAsset . NET . Files ;
1011
@@ -33,7 +34,7 @@ public class BundleFile
3334
3435 public uint Crc32 ;
3536
36- public static UnityCN ? ParseUnityCnInfo ( DataBuffer db , Header header , string ? key )
37+ public static UnityCN ? ParseUnityCnInfo ( IReader reader , Header header , string ? key )
3738 {
3839 var unityCnMask = VersionJudge1 ( ParseVersion ( header ) )
3940 ? ArchiveFlags . BlockInfoNeedPaddingAtStart
@@ -44,45 +45,45 @@ public class BundleFile
4445 key ??= Setting . DefaultUnityCNKey ;
4546 if ( key == null )
4647 throw new Exception ( $ "UnityCN key is required for decryption. UnityCN Flag Mask: { unityCnMask } ") ;
47- return new UnityCN ( db , key ) ;
48+ return new UnityCN ( reader , key ) ;
4849 }
4950 return null ;
5051 }
5152
52- public static void AlignAfterHeader ( DataBuffer db , Header header )
53+ public static void AlignAfterHeader ( IReader reader , Header header )
5354 {
5455 if ( header . Version >= 7 )
55- db . Align ( 16 ) ;
56+ reader . Align ( 16 ) ;
5657 else // temp fix for 2019.4.x
5758 {
5859 var version = ParseVersion ( header ) ;
5960 if ( version [ 0 ] == 2019 && version [ 1 ] == 4 && version [ 2 ] >= 30 )
60- db . Align ( 16 ) ;
61+ reader . Align ( 16 ) ;
6162 }
6263 }
6364
64- public static BlocksAndDirectoryInfo ParseDataInfo ( DataBuffer db , Header header )
65+ public static BlocksAndDirectoryInfo ParseDataInfo ( IReader reader , Header header )
6566 {
66- Span < byte > blocksInfoBytes = ( header . Flags & ArchiveFlags . BlocksInfoAtTheEnd ) == 0
67- ? db . ReadSpanBytes ( ( int ) header . CompressedBlocksInfoSize )
68- : db [ ( int ) ( header . Size - header . CompressedBlocksInfoSize ) .. ( int ) header . Size ] ;
67+ var blocksInfoBytes = ( header . Flags & ArchiveFlags . BlocksInfoAtTheEnd ) == 0
68+ ? reader . ReadOnlySpanBytes ( ( int ) header . CompressedBlocksInfoSize )
69+ : reader . ReadOnlySlice ( ( int ) ( header . Size - header . CompressedBlocksInfoSize ) , ( int ) header . CompressedBlocksInfoSize ) ;
6970 var compressionType = ( CompressionType ) ( header . Flags & ArchiveFlags . CompressionTypeMask ) ;
70- DataBuffer blocksInfoUncompressedData = new DataBuffer ( ( int ) header . UncompressedBlocksInfoSize ) ;
71- Compression . DecompressToBytes ( blocksInfoBytes , blocksInfoUncompressedData . AsSpan ( ) , compressionType ) ;
71+ MemoryBinaryIO blocksInfoUncompressedData = MemoryBinaryIO . Create ( ( int ) header . UncompressedBlocksInfoSize ) ;
72+ Compression . DecompressToBytes ( blocksInfoBytes , blocksInfoUncompressedData . AsWritableSpan , compressionType ) ;
7273 var dataInfo = BlocksAndDirectoryInfo . Parse ( blocksInfoUncompressedData ) ;
7374 if ( ! VersionJudge1 ( ParseVersion ( header ) ) && ( header . Flags & ArchiveFlags . BlockInfoNeedPaddingAtStart ) != 0 )
74- db . Align ( 16 ) ;
75+ reader . Align ( 16 ) ;
7576 return dataInfo ;
7677 }
7778
78- public static ( List < FileWrapper > , uint ) ParseFiles ( DataBuffer db , BlocksAndDirectoryInfo dataInfo , UnityCN ? unityCnInfo = null )
79+ public static ( List < FileWrapper > , uint ) ParseFiles ( IReader reader , BlocksAndDirectoryInfo dataInfo , UnityCN ? unityCnInfo = null )
7980 {
80- DataBuffer blocksBuffer = new DataBuffer ( dataInfo . BlocksInfo . Sum ( block => ( int ) block . UncompressedSize ) ) ;
81+ MemoryBinaryIO blocksBuffer = MemoryBinaryIO . Create ( dataInfo . BlocksInfo . Sum ( block => ( int ) block . UncompressedSize ) ) ;
8182 if ( unityCnInfo == null )
8283 foreach ( var blockInfo in dataInfo . BlocksInfo . AsReadOnlySpan ( ) )
8384 Compression . DecompressToBytes (
84- db . ReadSpanBytes ( ( int ) blockInfo . CompressedSize ) ,
85- blocksBuffer . ReadSpanBytes ( ( int ) blockInfo . UncompressedSize ) ,
85+ reader . ReadOnlySpanBytes ( ( int ) blockInfo . CompressedSize ) ,
86+ blocksBuffer . GetWritableSpan ( ( int ) blockInfo . UncompressedSize ) ,
8687 ( CompressionType ) ( blockInfo . Flags & StorageBlockFlags . CompressionTypeMask ) ) ;
8788 else
8889 {
@@ -93,23 +94,35 @@ public static (List<FileWrapper>, uint) ParseFiles(DataBuffer db, BlocksAndDirec
9394 var compressionType = ( CompressionType ) ( blockInfo . Flags & StorageBlockFlags . CompressionTypeMask ) ;
9495 if ( compressionType == CompressionType . Lz4 || compressionType == CompressionType . Lz4HC )
9596 unityCnInfo . DecryptAndDecompress (
96- db . ReadSpanBytes ( ( int ) blockInfo . CompressedSize ) ,
97- blocksBuffer . ReadSpanBytes ( ( int ) blockInfo . UncompressedSize ) ,
97+ reader . ReadOnlySpanBytes ( ( int ) blockInfo . CompressedSize ) ,
98+ blocksBuffer . GetWritableSpan ( ( int ) blockInfo . UncompressedSize ) ,
9899 i ) ;
99100 else
100101 throw new IOException ( $ "Unsupported compression type { compressionType } for UnityCN") ;
101102 }
102103 }
103104 blocksBuffer . Seek ( 0 ) ;
104105
105- var crc32 = CRC32 . CalculateCRC32 ( blocksBuffer . AsSpan ( ) ) ;
106+ var crc32 = CRC32 . CalculateCRC32 ( blocksBuffer . AsReadOnlySpan ) ;
106107
107108 var files = new List < FileWrapper > ( ) ;
108109 foreach ( var dir in dataInfo . DirectoryInfo . AsReadOnlySpan ( ) )
109- files . Add ( new FileWrapper ( new DataBuffer ( blocksBuffer . ReadSpanBytes ( ( int ) dir . Size ) . ToArray ( ) ) , dir ) ) ;
110+ files . Add ( new FileWrapper ( MemoryBinaryIO . Create ( blocksBuffer . ReadOnlySpanBytes ( ( int ) dir . Size ) . ToArray ( ) ) , dir ) ) ;
110111
111112 return ( files , crc32 ) ;
112113 }
114+
115+ // crc calculate disabled
116+ public static ( List < FileWrapper > , uint ) LazyParseFiles ( StreamReader reader , BlocksAndDirectoryInfo dataInfo , UnityCN ? unityCnInfo = null )
117+ {
118+ var blockStream = new BlockStream ( dataInfo . BlocksInfo , reader , unityCnInfo ) ;
119+ //var crc32 = CRC32.CalculateCRC32(blocksBuffer.AsReadOnlySpan);
120+ var files = new List < FileWrapper > ( ) ;
121+ foreach ( var dir in dataInfo . DirectoryInfo . AsReadOnlySpan ( ) )
122+ files . Add ( new FileWrapper ( new FileEntryStreamReader ( blockStream , dir ) , dir ) ) ;
123+
124+ return ( files , 0 ) ;
125+ }
113126
114127 public BundleFile ( Header header , BlocksAndDirectoryInfo dataInfo , List < FileWrapper > files , string ? key = null )
115128 {
@@ -119,14 +132,14 @@ public BundleFile(Header header, BlocksAndDirectoryInfo dataInfo, List<FileWrapp
119132 Files = files ;
120133 }
121134
122- public BundleFile ( DataBuffer db , string ? key = null )
135+ public BundleFile ( IReader reader , string ? key = null )
123136 {
124137 UnityCnKey = key ;
125- Header = Header . Parse ( db ) ;
126- UnityCnInfo = ParseUnityCnInfo ( db , Header , UnityCnKey ) ;
127- AlignAfterHeader ( db , Header ) ;
128- DataInfo = ParseDataInfo ( db , Header ) ;
129- ( Files , Crc32 ) = ParseFiles ( db , DataInfo , UnityCnInfo ) ;
138+ Header = Header . Parse ( reader ) ;
139+ UnityCnInfo = ParseUnityCnInfo ( reader , Header , UnityCnKey ) ;
140+ AlignAfterHeader ( reader , Header ) ;
141+ DataInfo = ParseDataInfo ( reader , Header ) ;
142+ ( Files , Crc32 ) = ( reader is StreamReader streamReader ) ? LazyParseFiles ( streamReader , DataInfo , UnityCnInfo ) : ParseFiles ( reader , DataInfo , UnityCnInfo ) ;
130143 }
131144
132145 /// <summary>
@@ -138,28 +151,28 @@ public BundleFile(DataBuffer db, string? key = null)
138151 /// </remarks>
139152 /// <param name="path">The file path to the BundleFile</param>
140153 /// <param name="key">Optional decryption key</param>
141- public BundleFile ( string path , string ? key = null ) : this ( DataBuffer . FromFile ( path ) , key ) { }
154+ public BundleFile ( string path , string ? key = null ) : this ( new FileStreamReader ( path ) , key ) { }
142155
143- public int Serialize ( DataBuffer db , CompressionType infoPacker = CompressionType . None , CompressionType dataPacker = CompressionType . None , string ? unityCnKey = null )
156+ /* public void Serialize(IWriter writer , CompressionType infoPacker = CompressionType.None, CompressionType dataPacker = CompressionType.None, string? unityCnKey = null)
144157 {
145158 if (Header == null || DataInfo == null || Files == null)
146159 throw new NullReferenceException("BundleFile has not read completely");
147160 var directoryInfo = new List<FileEntry>();
148161 var filesCapacity = Files.Sum(c =>
149162 {
150- if ( c . File is DataBuffer hdb ) return hdb . Capacity ;
163+ if (c.File is IReader r ) return r.Length ;
151164 if (c.File is SerializedFile sf) return sf.SerializeSize;
152165 return 0;
153166 });
154- DataBuffer filesBuffer = new DataBuffer ( ( int ) filesCapacity ) ;
167+ MemoryBinaryIO filesBuffer = MemoryBinaryIO.Create ((int)filesCapacity);
155168 Int64 offset = 0;
156169 foreach (var file in Files.AsReadOnlySpan())
157170 {
158171 int cabSize;
159172 switch (file.File)
160173 {
161- case DataBuffer dataBuffer :
162- cabSize = filesBuffer . WriteBytes ( dataBuffer . AsSpan ( ) ) ;
174+ case IReader r :
175+ cabSize = filesBuffer.WriteBytes(r. );
163176 break;
164177 case SerializedFile sf:
165178 cabSize = sf.Serialize(filesBuffer.SliceBufferToEnd());
@@ -182,14 +195,14 @@ public int Serialize(DataBuffer db, CompressionType infoPacker = CompressionType
182195 int chunkSize = (int)Math.Min(blocksSize, defaultChunkSize);
183196 var compressedSize = Compression.CompressToBytes(
184197 filesBuffer.ReadSpanBytes(chunkSize),
185- compressedBlocksDataBuffer . SliceForward ( ) ,
198+ compressedBlocksDataBuffer.SliceForward(),
186199 dataPacker);
187200 blocksInfo.Add(new StorageBlockInfo((UInt32)chunkSize, (UInt32)compressedSize, (StorageBlockFlags)dataPacker));
188201 blocksSize -= chunkSize;
189202 compressedBlocksDataBuffer.Advance((int)compressedSize);
190203 }
191204 compressedBlocksDataBuffer.Seek(0);
192-
205+
193206 UnityCN? unityCnInfo = null;
194207 var version = ParseVersion(Header);
195208 if (unityCnKey != null)
@@ -212,14 +225,14 @@ public int Serialize(DataBuffer db, CompressionType infoPacker = CompressionType
212225 else if (UnityCnKey != null)
213226 {
214227 var unityCnMask = VersionJudge1(version)
215- ? ArchiveFlags . BlockInfoNeedPaddingAtStart
228+ ? ArchiveFlags.BlockInfoNeedPaddingAtStart
216229 : ArchiveFlags.UnityCNEncryption | ArchiveFlags.UnityCNEncryptionNew;
217230 if (unityCnMask == (ArchiveFlags.UnityCNEncryption | ArchiveFlags.UnityCNEncryptionNew))
218231 unityCnMask = (Header.Flags & ArchiveFlags.UnityCNEncryptionNew) != 0 ?
219232 ArchiveFlags.UnityCNEncryptionNew : ArchiveFlags.UnityCNEncryption;
220233 Header.Flags &= ~unityCnMask;
221234 }
222-
235+
223236 var dataInfo = new BlocksAndDirectoryInfo(DataInfo.UncompressedDataHash, blocksInfo, directoryInfo);
224237 DataBuffer dataInfoBuffer = new DataBuffer((int)dataInfo.SerializeSize);
225238 dataInfo.Serialize(dataInfoBuffer);
@@ -230,37 +243,37 @@ public int Serialize(DataBuffer db, CompressionType infoPacker = CompressionType
230243 var header = new Header(Header.Signature, Header.Version, Header.UnityVersion, Header.UnityRevision,
231244 0, (uint)compressedBlocksInfoSize, (uint)uncompressedBlocksInfoSize,
232245 (Header.Flags & ~ArchiveFlags.CompressionTypeMask) | (ArchiveFlags)infoPacker);
233- db . EnsureCapacity ( ( int ) ( header . SerializeSize + 16 + compressedBlocksInfoSize + compressedBlocksDataBuffer . Length + unityCnInfo ? . SerializeSize ?? 0 ) ) ;
246+ writer .EnsureCapacity((int)(header.SerializeSize + 16 + compressedBlocksInfoSize + compressedBlocksDataBuffer.Length + unityCnInfo?.SerializeSize ?? 0));
234247 int size = 0;
235- size += header . Serialize ( db ) ;
248+ size += header.Serialize(writer );
236249 if (unityCnInfo != null)
237- size += unityCnInfo . Serialize ( db ) ;
250+ size += unityCnInfo.Serialize(writer );
238251 if (header.Version >= 7)
239- size += db . Align ( 16 ) ;
252+ size += writer .Align(16);
240253 else // temp fix for 2019.4.x
241254 if (version[0] == 2019 && version[1] == 4 && version[2] >= 30)
242- size += db . Align ( 16 ) ;
255+ size += writer .Align(16);
243256 if ((header.Flags & ArchiveFlags.BlocksInfoAtTheEnd) == 0) //0x40 BlocksAndDirectoryInfoCombined
244- size += db . WriteBytes ( compressedDataInfoBuffer . SliceForward ( ( int ) compressedBlocksInfoSize ) ) ;
257+ size += writer .WriteBytes(compressedDataInfoBuffer.SliceForward((int)compressedBlocksInfoSize));
245258 if (!VersionJudge1(version) &&(header.Flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
246- size += db . Align ( 16 ) ;
247- size += db . WriteBytes ( compressedBlocksDataBuffer . SliceForward ( compressedBlocksDataBuffer . Length ) ) ;
259+ size += writer .Align(16);
260+ size += writer .WriteBytes(compressedBlocksDataBuffer.SliceForward(compressedBlocksDataBuffer.Length));
248261 if ((header.Flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0) //kArchiveBlocksInfoAtTheEnd
249- size += db . WriteBytes ( compressedDataInfoBuffer . SliceForward ( ( int ) compressedBlocksInfoSize ) ) ;
262+ size += writer .WriteBytes(compressedDataInfoBuffer.SliceForward((int)compressedBlocksInfoSize));
250263 header.Size = size;
251- db . Seek ( 0 ) ;
252- header . Serialize ( db ) ;
264+ writer .Seek(0);
265+ header.Serialize(writer );
253266 return size;
254- }
267+ }*/
255268
256- public int Serialize ( string path , CompressionType infoPacker = CompressionType . None ,
269+ /* public int Serialize(string path, CompressionType infoPacker = CompressionType.None,
257270 CompressionType dataPacker = CompressionType.None, string? unityCnKey = null)
258271 {
259272 DataBuffer db = new DataBuffer(0);
260273 int size = Serialize(db, infoPacker, dataPacker, unityCnKey);
261274 db.WriteToFile(path, size);
262275 return size;
263- }
276+ }*/
264277
265278 public override string ToString ( )
266279 {
0 commit comments