1- using System . Text . RegularExpressions ;
1+ using System . Text ;
2+ using System . Text . RegularExpressions ;
23using UnityAsset . NET . Enums ;
4+ using UnityAsset . NET . Extensions ;
35using UnityAsset . NET . Files . BundleFiles ;
46using UnityAsset . NET . Files . SerializedFiles ;
57using UnityAsset . NET . IO ;
@@ -77,16 +79,17 @@ public static (List<FileWrapper>, uint) ParseFiles(DataBuffer db, BlocksAndDirec
7779 {
7880 DataBuffer blocksBuffer = new DataBuffer ( dataInfo . BlocksInfo . Sum ( block => ( int ) block . UncompressedSize ) ) ;
7981 if ( unityCnInfo == null )
80- foreach ( var blockInfo in dataInfo . BlocksInfo )
82+ foreach ( var blockInfo in dataInfo . BlocksInfo . AsReadOnlySpan ( ) )
8183 Compression . DecompressToBytes (
8284 db . ReadSpanBytes ( ( int ) blockInfo . CompressedSize ) ,
8385 blocksBuffer . ReadSpanBytes ( ( int ) blockInfo . UncompressedSize ) ,
8486 ( CompressionType ) ( blockInfo . Flags & StorageBlockFlags . CompressionTypeMask ) ) ;
8587 else
8688 {
87- for ( int i = 0 ; i < dataInfo . BlocksInfo . Count ; i ++ )
89+ var blocksInfoSpan = dataInfo . BlocksInfo . AsReadOnlySpan ( ) ;
90+ for ( int i = 0 ; i < blocksInfoSpan . Length ; i ++ )
8891 {
89- var blockInfo = dataInfo . BlocksInfo [ i ] ;
92+ var blockInfo = blocksInfoSpan [ i ] ;
9093 var compressionType = ( CompressionType ) ( blockInfo . Flags & StorageBlockFlags . CompressionTypeMask ) ;
9194 if ( compressionType == CompressionType . Lz4 || compressionType == CompressionType . Lz4HC )
9295 unityCnInfo . DecryptAndDecompress (
@@ -102,19 +105,8 @@ public static (List<FileWrapper>, uint) ParseFiles(DataBuffer db, BlocksAndDirec
102105 var crc32 = CRC32 . CalculateCRC32 ( blocksBuffer . AsSpan ( ) ) ;
103106
104107 var files = new List < FileWrapper > ( ) ;
105- foreach ( var dir in dataInfo . DirectoryInfo )
106- {
107- if ( dir . Path . StartsWith ( "CAB-" ) && ! dir . Path . EndsWith ( ".resS" ) )
108- {
109- var cabBuffer = blocksBuffer . SliceBuffer ( ( int ) dir . Size ) ;
110- files . Add ( new FileWrapper ( SerializedFile . Parse ( cabBuffer ) , dir ) ) ;
111- blocksBuffer . Advance ( ( int ) dir . Size ) ;
112- }
113- else
114- {
115- files . Add ( new FileWrapper ( new DataBuffer ( blocksBuffer . ReadSpanBytes ( ( int ) dir . Size ) . ToArray ( ) ) , dir ) ) ;
116- }
117- }
108+ foreach ( var dir in dataInfo . DirectoryInfo . AsReadOnlySpan ( ) )
109+ files . Add ( new FileWrapper ( new DataBuffer ( blocksBuffer . ReadSpanBytes ( ( int ) dir . Size ) . ToArray ( ) ) , dir ) ) ;
118110
119111 return ( files , crc32 ) ;
120112 }
@@ -137,9 +129,18 @@ public BundleFile(DataBuffer db, string? key = null)
137129 ( Files , Crc32 ) = ParseFiles ( db , DataInfo , UnityCnInfo ) ;
138130 }
139131
132+ /// <summary>
133+ /// Parses only the BundleFile container structure without further parsing the contained SerializedFile format.
134+ /// </summary>
135+ /// <remarks>
136+ /// This method stops at the BundleFile level and does not process the internal SerializedFile structures.
137+ /// If you need full parsing including SerializedFile format conversion, use <see cref="BundleFileExtensions.ParseFilesWithTypeConversion"/> instead.
138+ /// </remarks>
139+ /// <param name="path">The file path to the BundleFile</param>
140+ /// <param name="key">Optional decryption key</param>
140141 public BundleFile ( string path , string ? key = null ) : this ( DataBuffer . FromFile ( path ) , key ) { }
141142
142- public void Serialize ( DataBuffer db , CompressionType infoPacker = CompressionType . None , CompressionType dataPacker = CompressionType . None , string ? unityCnKey = null )
143+ public int Serialize ( DataBuffer db , CompressionType infoPacker = CompressionType . None , CompressionType dataPacker = CompressionType . None , string ? unityCnKey = null )
143144 {
144145 if ( Header == null || DataInfo == null || Files == null )
145146 throw new NullReferenceException ( "BundleFile has not read completely" ) ;
@@ -152,20 +153,17 @@ public void Serialize(DataBuffer db, CompressionType infoPacker = CompressionTyp
152153 } ) ;
153154 DataBuffer filesBuffer = new DataBuffer ( ( int ) filesCapacity ) ;
154155 Int64 offset = 0 ;
155- foreach ( var file in Files )
156+ foreach ( var file in Files . AsReadOnlySpan ( ) )
156157 {
157- Int64 cabSize ;
158+ int cabSize ;
158159 switch ( file . File )
159160 {
160161 case DataBuffer dataBuffer :
161- filesBuffer . WriteBytes ( dataBuffer . AsSpan ( ) ) ;
162- cabSize = dataBuffer . Length ;
162+ cabSize = filesBuffer . WriteBytes ( dataBuffer . AsSpan ( ) ) ;
163163 break ;
164164 case SerializedFile sf :
165- var subBuffer = filesBuffer . SliceBufferToEnd ( ) ;
166- sf . Serialize ( subBuffer ) ;
167- filesBuffer . Advance ( subBuffer . Position ) ;
168- cabSize = subBuffer . Position ;
165+ cabSize = sf . Serialize ( filesBuffer . SliceBufferToEnd ( ) ) ;
166+ filesBuffer . Advance ( cabSize ) ;
169167 break ;
170168 default :
171169 throw new Exception ( $ "Unexpected type: { file . File . GetType ( ) . Name } ") ;
@@ -199,9 +197,10 @@ public void Serialize(DataBuffer db, CompressionType infoPacker = CompressionTyp
199197 unityCnInfo = new UnityCN ( unityCnKey ) ;
200198 if ( dataPacker == CompressionType . Lz4 || dataPacker == CompressionType . Lz4HC )
201199 {
202- for ( int i = 0 ; i < blocksInfo . Count ; i ++ )
200+ var blocksInfoSpan = blocksInfo . AsSpan ( ) ;
201+ for ( int i = 0 ; i < blocksInfoSpan . Length ; i ++ )
203202 {
204- var blockInfo = blocksInfo [ i ] ;
203+ var blockInfo = blocksInfoSpan [ i ] ;
205204 blockInfo . Flags |= ( StorageBlockFlags ) 0x100 ;
206205 unityCnInfo . EncryptBlock ( compressedBlocksDataBuffer . ReadSpanBytes ( ( int ) blockInfo . CompressedSize ) , ( int ) blockInfo . CompressedSize , i ) ;
207206 }
@@ -232,35 +231,46 @@ public void Serialize(DataBuffer db, CompressionType infoPacker = CompressionTyp
232231 0 , ( uint ) compressedBlocksInfoSize , ( uint ) uncompressedBlocksInfoSize ,
233232 ( Header . Flags & ~ ArchiveFlags . CompressionTypeMask ) | ( ArchiveFlags ) infoPacker ) ;
234233 db . EnsureCapacity ( ( int ) ( header . SerializeSize + 16 + compressedBlocksInfoSize + compressedBlocksDataBuffer . Length + unityCnInfo ? . SerializeSize ?? 0 ) ) ;
235- header . Serialize ( db ) ;
234+ int size = 0 ;
235+ size += header . Serialize ( db ) ;
236236 if ( unityCnInfo != null )
237- unityCnInfo . Serialize ( db ) ;
237+ size += unityCnInfo . Serialize ( db ) ;
238238 if ( header . Version >= 7 )
239- db . Align ( 16 ) ;
239+ size += db . Align ( 16 ) ;
240240 else // temp fix for 2019.4.x
241- {
242241 if ( version [ 0 ] == 2019 && version [ 1 ] == 4 && version [ 2 ] >= 30 )
243- db . Align ( 16 ) ;
244- }
242+ size += db . Align ( 16 ) ;
245243 if ( ( header . Flags & ArchiveFlags . BlocksInfoAtTheEnd ) == 0 ) //0x40 BlocksAndDirectoryInfoCombined
246- db . WriteBytes ( compressedDataInfoBuffer . SliceForward ( ( int ) compressedBlocksInfoSize ) ) ;
244+ size += db . WriteBytes ( compressedDataInfoBuffer . SliceForward ( ( int ) compressedBlocksInfoSize ) ) ;
247245 if ( ! VersionJudge1 ( version ) && ( header . Flags & ArchiveFlags . BlockInfoNeedPaddingAtStart ) != 0 )
248- db . Align ( 16 ) ;
249- db . WriteBytes ( compressedBlocksDataBuffer . SliceForward ( compressedBlocksDataBuffer . Length ) ) ;
246+ size += db . Align ( 16 ) ;
247+ size += db . WriteBytes ( compressedBlocksDataBuffer . SliceForward ( compressedBlocksDataBuffer . Length ) ) ;
250248 if ( ( header . Flags & ArchiveFlags . BlocksInfoAtTheEnd ) != 0 ) //kArchiveBlocksInfoAtTheEnd
251- db . WriteBytes ( compressedDataInfoBuffer . SliceForward ( ( int ) compressedBlocksInfoSize ) ) ;
252- var size = db . Position ;
249+ size += db . WriteBytes ( compressedDataInfoBuffer . SliceForward ( ( int ) compressedBlocksInfoSize ) ) ;
253250 header . Size = size ;
254251 db . Seek ( 0 ) ;
255252 header . Serialize ( db ) ;
253+ return size ;
256254 }
257255
258- public void Serialize ( string path , CompressionType infoPacker = CompressionType . None ,
256+ public int Serialize ( string path , CompressionType infoPacker = CompressionType . None ,
259257 CompressionType dataPacker = CompressionType . None , string ? unityCnKey = null )
260258 {
261259 DataBuffer db = new DataBuffer ( 0 ) ;
262- Serialize ( db , infoPacker , dataPacker , unityCnKey ) ;
263- db . WriteToFile ( path ) ;
260+ int size = Serialize ( db , infoPacker , dataPacker , unityCnKey ) ;
261+ db . WriteToFile ( path , size ) ;
262+ return size ;
263+ }
264+
265+ public override string ToString ( )
266+ {
267+ StringBuilder sb = new StringBuilder ( ) ;
268+ sb . AppendLine ( $ "Header: { Header } ") ;
269+ sb . AppendLine ( $ "DataInfo: { DataInfo } ") ;
270+ var filesSpan = Files . AsSpan ( ) ;
271+ for ( int i = 0 ; i < filesSpan . Length ; ++ i )
272+ sb . AppendLine ( $ "File { i } : { filesSpan [ i ] } ") ;
273+ return sb . ToString ( ) ;
264274 }
265275
266276 public static int [ ] ParseVersion ( Header header )
0 commit comments