Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize DepotManifest Serialization #1337

Merged
merged 4 commits into from
Jul 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 26 additions & 29 deletions SteamKit2/SteamKit2/Types/DepotManifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,25 +219,6 @@ public bool DecryptFilenames(byte[] encryptionKey)
return true;
}

/// <summary>
/// Serializes depot manifest and saves the output to a file.
/// </summary>
/// <param name="filename">Output file name.</param>
/// <returns><c>true</c> if serialization was successful; otherwise, <c>false</c>.</returns>
public bool SaveToFile( string filename )
{
using var fs = File.Open( filename, FileMode.Create );
using var bw = new BinaryWriter( fs );
var data = Serialize();
if ( data != null )
{
bw.Write( data );
return true;
}

return false;
}

/// <summary>
/// Loads binary manifest from a file and deserializes it.
/// </summary>
Expand Down Expand Up @@ -371,12 +352,34 @@ void ParseProtobufManifestMetadata(ContentManifestMetadata metadata)
EncryptedCRC = metadata.crc_encrypted;
}

byte[]? Serialize()
class ChunkIdComparer : IEqualityComparer<byte[]>
{
public bool Equals( byte[]? x, byte[]? y )
{
if ( ReferenceEquals( x, y ) ) return true;
if ( x == null || y == null ) return false;
return x.SequenceEqual( y );
}

public int GetHashCode( byte[] obj )
{
ArgumentNullException.ThrowIfNull( obj );

// ChunkID is SHA-1, so we can just use the first 4 bytes
return BitConverter.ToInt32( obj, 0 );
}
}

/// <summary>
/// Serializes the depot manifest into the provided output stream.
/// </summary>
/// <param name="output">The stream to which the serialized depot manifest will be written.</param>
public void Serialize( Stream output )
{
DebugLog.Assert( Files != null, nameof( DepotManifest ), "Files was null when attempting to serialize manifest." );

var payload = new ContentManifestPayload();
var uniqueChunks = new List<byte[]>();
var uniqueChunks = new HashSet<byte[]>( new ChunkIdComparer() );

foreach ( var file in Files )
{
Expand Down Expand Up @@ -409,10 +412,7 @@ void ParseProtobufManifestMetadata(ContentManifestMetadata metadata)
protochunk.cb_compressed = chunk.CompressedLength;

protofile.chunks.Add( protochunk );
if ( !uniqueChunks.Exists( x => x.SequenceEqual( chunk.ChunkID! ) ) )
{
uniqueChunks.Add( chunk.ChunkID! );
}
uniqueChunks.Add( chunk.ChunkID! );
}

payload.mappings.Add( protofile );
Expand Down Expand Up @@ -450,8 +450,7 @@ void ParseProtobufManifestMetadata(ContentManifestMetadata metadata)
}
}

using var ms = new MemoryStream();
using var bw = new BinaryWriter( ms );
using var bw = new BinaryWriter( output, Encoding.Default, true );

// Write Protobuf payload
using ( var ms_payload = new MemoryStream() )
Expand All @@ -477,8 +476,6 @@ void ParseProtobufManifestMetadata(ContentManifestMetadata metadata)

// Write EOF marker
bw.Write( DepotManifest.PROTOBUF_ENDOFMANIFEST_MAGIC );

return ms.ToArray();
}
}
}
Loading