Skip to content

Commit e3f08f9

Browse files
committed
Bundle level serialize support
1 parent 05918fd commit e3f08f9

14 files changed

Lines changed: 655 additions & 331 deletions

UnityAsset.NET/Files/BundleFiles/BlocksAndDirectoryInfo.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,12 @@ public BlocksAndDirectoryInfo(
2525
reader.ReadArray(FileEntry.Parse)
2626
);
2727

28-
/*public void Serialize(IWriter writer)
28+
public void Serialize(IWriter writer)
2929
{
3030
writer.WriteBytes(UncompressedDataHash);
31-
writer.WriteListWithCount(BlocksInfo, (w, info) => info.Serialize(w));
32-
writer.WriteListWithCount(DirectoryInfo, (w, info) => info.Serialize(w));
31+
writer.WriteArray(BlocksInfo, (w, info) => info.Serialize(w));
32+
writer.WriteArray(DirectoryInfo, (w, info) => info.Serialize(w));
3333
}
34-
35-
public long SerializeSize => UncompressedDataHash.Length + 8 +
36-
BlocksInfo.Sum(item => item.SerializeSize) +
37-
DirectoryInfo.Sum(item => item.SerializeSize);*/
3834

3935
public override string ToString()
4036
{

UnityAsset.NET/Files/BundleFiles/BundleFile.cs

Lines changed: 89 additions & 164 deletions
Large diffs are not rendered by default.

UnityAsset.NET/Files/BundleFiles/FileEntry.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,13 @@ public FileEntry(ulong offset, ulong size, UInt32 flags, string path)
2525
reader.ReadNullTerminatedString()
2626
);
2727

28-
/*public void Serialize(IWriter writer)
28+
public void Serialize(IWriter writer)
2929
{
30-
writer.WriteInt64(Offset);
31-
writer.WriteInt64(Size);
30+
writer.WriteUInt64(Offset);
31+
writer.WriteUInt64(Size);
3232
writer.WriteUInt32(Flags);
3333
writer.WriteNullTerminatedString(Path);
3434
}
35-
36-
public long SerializeSize => 21 + Path.Length;*/
3735

3836
public override string ToString()
3937
{

UnityAsset.NET/Files/BundleFiles/Header.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ public Header(string signature, UInt32 version, string unityVersion, string unit
4040
(ArchiveFlags)reader.ReadUInt32()
4141
);
4242

43-
/*public void Serialize(IWriter writer)
43+
public void Serialize(IWriter writer)
4444
{
4545
writer.WriteNullTerminatedString(Signature);
4646
writer.WriteUInt32(Version);
4747
writer.WriteNullTerminatedString(UnityVersion);
48-
writer.WriteNullTerminatedString(UnityRevision);
48+
writer.WriteNullTerminatedString(UnityRevision.ToString());
4949
writer.WriteInt64(Size);
5050
writer.WriteUInt32(CompressedBlocksInfoSize);
5151
writer.WriteUInt32(UncompressedBlocksInfoSize);
5252
writer.WriteUInt32((UInt32)Flags);
5353
}
5454

55-
public long SerializeSize => 27 + Signature.Length + UnityVersion.Length + UnityRevision.Length;*/
55+
public long SerializeSize => 27 + Signature.Length + UnityVersion.Length + UnityRevision.ToString().Length;
5656

5757
public override string ToString()
5858
{

UnityAsset.NET/Files/BundleFiles/StorageBlockInfo.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,12 @@ public StorageBlockInfo(UInt32 uncompressedSize, UInt32 compressedSize, StorageB
2323
(StorageBlockFlags)reader.ReadUInt16()
2424
);
2525

26-
/*public void Serialize(IWriter writer) {
26+
public void Serialize(IWriter writer) {
2727
writer.WriteUInt32(UncompressedSize);
2828
writer.WriteUInt32(CompressedSize);
2929
writer.WriteUInt16((UInt16)Flags);
3030
}
3131

32-
public long SerializeSize => 10;*/
33-
3432
public override string ToString()
3533
{
3634
StringBuilder sb = new StringBuilder();

UnityAsset.NET/Files/BundleFiles/UnityCN.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public sealed unsafe class UnityCN
1111
private const string Signature = "#$unity3dchina!@";
1212

1313
private ICryptoTransform _encryptor;
14-
14+
public string Key;
1515
public UInt32 Value;
1616
public readonly byte[] InfoBytes;
1717
public readonly byte[] InfoKey;
@@ -32,6 +32,7 @@ public UnityCN(IReader reader, string key)
3232
{
3333
if (key.Length != 32 && key.Length != 16)
3434
throw new ArgumentException("key must be 32 or 16 characters long");
35+
Key = key;
3536
using var aes = Aes.Create();
3637
aes.Mode = CipherMode.ECB;
3738
aes.Key = Convert.FromHexString(key);
@@ -74,6 +75,7 @@ public UnityCN(string key)
7475
{
7576
if (key.Length != 32 && key.Length != 16)
7677
throw new ArgumentException("key must be 32 or 16 characters long");
78+
Key = key;
7779
using var aes = Aes.Create();
7880
aes.Mode = CipherMode.ECB;
7981
aes.Key = Convert.FromHexString(key);
@@ -131,7 +133,7 @@ private void Reset()
131133
}
132134
}
133135

134-
/*public void Serialize(IWriter writer)
136+
public void Serialize(IWriter writer)
135137
{
136138
writer.WriteUInt32(Value);
137139
writer.WriteBytes(InfoBytes);
@@ -142,7 +144,7 @@ private void Reset()
142144
writer.WriteByte(0);
143145
}
144146

145-
public long SerializeSize => 70;*/
147+
public long SerializeSize => 70;
146148

147149
public void DecryptBlock(Span<byte> bytes, int size, int index)
148150
{

UnityAsset.NET/IO/IReader.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,17 @@ public interface IReader : ISeek
2828

2929
public Endianness Endian { get; set; }
3030
public long Remaining => Length - Position;
31-
31+
public int Read(Span<byte> buffer, int offset, int count);
3232
public byte ReadByte();
3333
public sbyte ReadSByte() => (sbyte)ReadByte();
3434
public byte[] ReadBytes(int count);
35-
public void ReadExactly(Span<byte> buffer);
35+
36+
public void ReadExactly(Span<byte> buffer)
37+
{
38+
var bytesRead = Read(buffer, 0, buffer.Length);
39+
if (bytesRead != buffer.Length)
40+
throw new EndOfStreamException();
41+
}
3642
public bool ReadBoolean() => ReadByte() != 0;
3743
public sbyte ReadInt8() => (sbyte)ReadByte();
3844
public byte ReadUInt8() => ReadByte();

UnityAsset.NET/IO/IWriter.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public interface IWriter : ISeek
2727
public void WriteByte(byte value);
2828
public void WriteSByte(sbyte value) => WriteByte((byte)value);
2929
public void WriteBytes(ReadOnlySpan<byte> bytes);
30+
public ulong WriteBytes(IReader reader);
3031
private void WriteBytes(byte value, ulong count)
3132
{
3233
for (ulong i = 0; i < count; i++)
@@ -57,6 +58,20 @@ public void WriteInt32(int value)
5758
else
5859
WriteBytes(BitConverter.GetBytes(value));
5960
}
61+
public void WriteUInt32(uint value)
62+
{
63+
if (NeedReverse)
64+
WriteBytes(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(value)));
65+
else
66+
WriteBytes(BitConverter.GetBytes(value));
67+
}
68+
public void WriteInt64(long value)
69+
{
70+
if (NeedReverse)
71+
WriteBytes(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(value)));
72+
else
73+
WriteBytes(BitConverter.GetBytes(value));
74+
}
6075
public void WriteUInt64(ulong value)
6176
{
6277
if (NeedReverse)
@@ -107,6 +122,25 @@ public void WriteListWithAlign<T>(int count, List<T> list, Action<IWriter, T> wr
107122
}
108123
public void WriteListWithAlign<T>(List<T> list, Action<IWriter, T> writer, bool requiresAlign) =>
109124
WriteListWithAlign(list.Count, list, writer, requiresAlign);
125+
public void WriteArray<T>(int count, T[] array, Action<IWriter, T> writer)
126+
{
127+
WriteInt32(count);
128+
foreach (var item in array)
129+
writer(this, item);
130+
}
131+
public void WriteArray<T>(T[] array, Action<IWriter, T> writer) => WriteArray(array.Length, array, writer);
132+
public void WriteArrayWithAlign<T>(int count, T[] array, Action<IWriter, T> writer, bool requiresAlign)
133+
{
134+
WriteInt32(count);
135+
foreach (var item in array)
136+
{
137+
writer(this, item);
138+
if (requiresAlign)
139+
Align(4);
140+
}
141+
}
142+
public void WriteArrayWithAlign<T>(T[] array, Action<IWriter, T> writer, bool requiresAlign) =>
143+
WriteArrayWithAlign(array.Length, array, writer, requiresAlign);
110144
public void WritePairWithAlign<TK, TV>((TK, TV) value, Action<IWriter, TK> keyWriter,
111145
Action<IWriter, TV> valueWriter, bool keyRequiresAlign, bool valueRequiresAlign) where TK : notnull
112146
{

UnityAsset.NET/IO/Reader/BlockReader.cs

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,24 @@ private void EnsureBlockLoaded(long position)
259259

260260
public Endianness Endian { get; set; }
261261

262+
public int Read(Span<byte> buffer, int offset, int count)
263+
{
264+
int written = 0;
265+
while (written < buffer.Length - offset && ((IReader)this).Remaining > 0)
266+
{
267+
EnsureBlockLoaded(Position);
268+
269+
var toCopy = Math.Min(count - written, (int)BufferRemaining);
270+
271+
_buffer.AsSpan((int)BufferPos, toCopy)
272+
.CopyTo(buffer.Slice(offset + written, toCopy));
273+
274+
Position += (uint)toCopy;
275+
written += toCopy;
276+
}
277+
278+
return written;
279+
}
262280
public byte ReadByte()
263281
{
264282
EnsureBlockLoaded(Position);
@@ -269,33 +287,12 @@ public byte ReadByte()
269287

270288
public byte[] ReadBytes(int count)
271289
{
272-
if (count < 0)
273-
throw new ArgumentOutOfRangeException(nameof(count));
274-
if (count == 0)
275-
return [];
276290
if ((uint)count > ((IReader)this).Remaining)
277291
throw new EndOfStreamException();
278292
byte[] bytes = new byte[count];
279-
ReadExactly(bytes);
293+
((IReader)this).ReadExactly(bytes);
280294
return bytes;
281295
}
282-
public void ReadExactly(Span<byte> buffer)
283-
{
284-
int written = 0;
285-
while (written < buffer.Length)
286-
{
287-
EnsureBlockLoaded(Position);
288-
289-
var available = (int)BufferRemaining;
290-
var toCopy = Math.Min(buffer.Length - written, available);
291-
292-
_buffer.AsSpan((int)BufferPos, toCopy)
293-
.CopyTo(buffer.Slice(written, toCopy));
294-
295-
Position += (uint)toCopy;
296-
written += toCopy;
297-
}
298-
}
299296
public short ReadInt16()
300297
{
301298
EnsureBlockLoaded(Position);
@@ -310,7 +307,7 @@ public short ReadInt16()
310307
}
311308

312309
Span<byte> tmp = stackalloc byte[2];
313-
ReadExactly(tmp);
310+
((IReader)this).ReadExactly(tmp);
314311
return Endian == Endianness.BigEndian
315312
? BinaryPrimitives.ReadInt16BigEndian(tmp)
316313
: BinaryPrimitives.ReadInt16LittleEndian(tmp);
@@ -329,7 +326,7 @@ public ushort ReadUInt16()
329326
}
330327

331328
Span<byte> tmp = stackalloc byte[2];
332-
ReadExactly(tmp);
329+
((IReader)this).ReadExactly(tmp);
333330
return Endian == Endianness.BigEndian
334331
? BinaryPrimitives.ReadUInt16BigEndian(tmp)
335332
: BinaryPrimitives.ReadUInt16LittleEndian(tmp);
@@ -348,7 +345,7 @@ public int ReadInt32()
348345
}
349346

350347
Span<byte> tmp = stackalloc byte[4];
351-
ReadExactly(tmp);
348+
((IReader)this).ReadExactly(tmp);
352349
return Endian == Endianness.BigEndian
353350
? BinaryPrimitives.ReadInt32BigEndian(tmp)
354351
: BinaryPrimitives.ReadInt32LittleEndian(tmp);
@@ -367,7 +364,7 @@ public uint ReadUInt32()
367364
}
368365

369366
Span<byte> tmp = stackalloc byte[4];
370-
ReadExactly(tmp);
367+
((IReader)this).ReadExactly(tmp);
371368
return Endian == Endianness.BigEndian
372369
? BinaryPrimitives.ReadUInt32BigEndian(tmp)
373370
: BinaryPrimitives.ReadUInt32LittleEndian(tmp);
@@ -386,7 +383,7 @@ public long ReadInt64()
386383
}
387384

388385
Span<byte> tmp = stackalloc byte[8];
389-
ReadExactly(tmp);
386+
((IReader)this).ReadExactly(tmp);
390387
return Endian == Endianness.BigEndian
391388
? BinaryPrimitives.ReadInt64BigEndian(tmp)
392389
: BinaryPrimitives.ReadInt64LittleEndian(tmp);
@@ -405,7 +402,7 @@ public ulong ReadUInt64()
405402
}
406403

407404
Span<byte> tmp = stackalloc byte[8];
408-
ReadExactly(tmp);
405+
((IReader)this).ReadExactly(tmp);
409406
return Endian == Endianness.BigEndian
410407
? BinaryPrimitives.ReadUInt64BigEndian(tmp)
411408
: BinaryPrimitives.ReadUInt64LittleEndian(tmp);
@@ -424,7 +421,7 @@ public float ReadSingle()
424421
}
425422

426423
Span<byte> tmp = stackalloc byte[4];
427-
ReadExactly(tmp);
424+
((IReader)this).ReadExactly(tmp);
428425
return Endian == Endianness.BigEndian
429426
? BinaryPrimitives.ReadSingleBigEndian(tmp)
430427
: BinaryPrimitives.ReadSingleLittleEndian(tmp);
@@ -443,7 +440,7 @@ public double ReadDouble()
443440
}
444441

445442
Span<byte> tmp = stackalloc byte[8];
446-
ReadExactly(tmp);
443+
((IReader)this).ReadExactly(tmp);
447444
return Endian == Endianness.BigEndian
448445
? BinaryPrimitives.ReadDoubleBigEndian(tmp)
449446
: BinaryPrimitives.ReadDoubleLittleEndian(tmp);

0 commit comments

Comments
 (0)