mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2025-01-31 06:51:33 -08:00
3b46bb73f7
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0052 warnings * Address dotnet format CA1816 warnings * Address or silence dotnet format CA1069 warnings * Address or silence dotnet format CA2211 warnings * Address remaining dotnet format analyzer warnings * Address review comments * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Format if-blocks correctly * Run dotnet format whitespace after rebase * Run dotnet format style after rebase * Another rebase, another dotnet format run * Run dotnet format style after rebase * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Disable 'prefer switch expression' rule * Add comments to disabled warnings * Remove a few unused parameters * Replace MmeShadowScratch with Array256<uint> * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Start working on disabled warnings * Fix and silence a few dotnet-format warnings again * Run dotnet format after rebase * Address IDE0251 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First pass of dotnet format * Add unsafe dotnet format changes * Fix typos * Add trailing commas * Disable formatting for FormatTable * Address review feedback
217 lines
7.8 KiB
C#
217 lines
7.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|
{
|
|
/// <summary>
|
|
/// Binary data serializer.
|
|
/// </summary>
|
|
struct BinarySerializer
|
|
{
|
|
private readonly Stream _stream;
|
|
private Stream _activeStream;
|
|
|
|
/// <summary>
|
|
/// Creates a new binary serializer.
|
|
/// </summary>
|
|
/// <param name="stream">Stream to read from or write into</param>
|
|
public BinarySerializer(Stream stream)
|
|
{
|
|
_stream = stream;
|
|
_activeStream = stream;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads data from the stream.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the data</typeparam>
|
|
/// <param name="data">Data read</param>
|
|
public readonly void Read<T>(ref T data) where T : unmanaged
|
|
{
|
|
Span<byte> buffer = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref data, 1));
|
|
for (int offset = 0; offset < buffer.Length;)
|
|
{
|
|
offset += _activeStream.Read(buffer[offset..]);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to read data from the stream.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the data</typeparam>
|
|
/// <param name="data">Data read</param>
|
|
/// <returns>True if the read was successful, false otherwise</returns>
|
|
public readonly bool TryRead<T>(ref T data) where T : unmanaged
|
|
{
|
|
// Length is unknown on compressed streams.
|
|
if (_activeStream == _stream)
|
|
{
|
|
int size = Unsafe.SizeOf<T>();
|
|
if (_activeStream.Length - _activeStream.Position < size)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Read(ref data);
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads data prefixed with a magic and size from the stream.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the data</typeparam>
|
|
/// <param name="data">Data read</param>
|
|
/// <param name="magic">Expected magic value, for validation</param>
|
|
public readonly void ReadWithMagicAndSize<T>(ref T data, uint magic) where T : unmanaged
|
|
{
|
|
uint actualMagic = 0;
|
|
int size = 0;
|
|
Read(ref actualMagic);
|
|
Read(ref size);
|
|
|
|
if (actualMagic != magic)
|
|
{
|
|
throw new DiskCacheLoadException(DiskCacheLoadResult.FileCorruptedInvalidMagic);
|
|
}
|
|
|
|
// Structs are expected to expand but not shrink between versions.
|
|
if (size > Unsafe.SizeOf<T>())
|
|
{
|
|
throw new DiskCacheLoadException(DiskCacheLoadResult.FileCorruptedInvalidLength);
|
|
}
|
|
|
|
Span<byte> buffer = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref data, 1))[..size];
|
|
for (int offset = 0; offset < buffer.Length;)
|
|
{
|
|
offset += _activeStream.Read(buffer[offset..]);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes data into the stream.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the data</typeparam>
|
|
/// <param name="data">Data to be written</param>
|
|
public readonly void Write<T>(ref T data) where T : unmanaged
|
|
{
|
|
Span<byte> buffer = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref data, 1));
|
|
_activeStream.Write(buffer);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes data prefixed with a magic and size into the stream.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the data</typeparam>
|
|
/// <param name="data">Data to write</param>
|
|
/// <param name="magic">Magic value to write</param>
|
|
public readonly void WriteWithMagicAndSize<T>(ref T data, uint magic) where T : unmanaged
|
|
{
|
|
int size = Unsafe.SizeOf<T>();
|
|
Write(ref magic);
|
|
Write(ref size);
|
|
Span<byte> buffer = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref data, 1));
|
|
_activeStream.Write(buffer);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates that all data that will be read from the stream has been compressed.
|
|
/// </summary>
|
|
public void BeginCompression()
|
|
{
|
|
CompressionAlgorithm algorithm = CompressionAlgorithm.None;
|
|
Read(ref algorithm);
|
|
|
|
if (algorithm == CompressionAlgorithm.Deflate)
|
|
{
|
|
_activeStream = new DeflateStream(_stream, CompressionMode.Decompress, true);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates that all data that will be written into the stream should be compressed.
|
|
/// </summary>
|
|
/// <param name="algorithm">Compression algorithm that should be used</param>
|
|
public void BeginCompression(CompressionAlgorithm algorithm)
|
|
{
|
|
Write(ref algorithm);
|
|
|
|
if (algorithm == CompressionAlgorithm.Deflate)
|
|
{
|
|
_activeStream = new DeflateStream(_stream, CompressionLevel.SmallestSize, true);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates the end of a compressed chunck.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Any data written after this will not be compressed unless <see cref="BeginCompression(CompressionAlgorithm)"/> is called again.
|
|
/// Any data read after this will be assumed to be uncompressed unless <see cref="BeginCompression"/> is called again.
|
|
/// </remarks>
|
|
public void EndCompression()
|
|
{
|
|
if (_activeStream != _stream)
|
|
{
|
|
_activeStream.Dispose();
|
|
_activeStream = _stream;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads compressed data from the stream.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <paramref name="data"/> must have the exact length of the uncompressed data,
|
|
/// otherwise decompression will fail.
|
|
/// </remarks>
|
|
/// <param name="stream">Stream to read from</param>
|
|
/// <param name="data">Buffer to write the uncompressed data into</param>
|
|
public static void ReadCompressed(Stream stream, Span<byte> data)
|
|
{
|
|
CompressionAlgorithm algorithm = (CompressionAlgorithm)stream.ReadByte();
|
|
|
|
switch (algorithm)
|
|
{
|
|
case CompressionAlgorithm.None:
|
|
stream.Read(data);
|
|
break;
|
|
case CompressionAlgorithm.Deflate:
|
|
stream = new DeflateStream(stream, CompressionMode.Decompress, true);
|
|
for (int offset = 0; offset < data.Length;)
|
|
{
|
|
offset += stream.Read(data[offset..]);
|
|
}
|
|
stream.Dispose();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compresses and writes the compressed data into the stream.
|
|
/// </summary>
|
|
/// <param name="stream">Stream to write into</param>
|
|
/// <param name="data">Data to compress</param>
|
|
/// <param name="algorithm">Compression algorithm to be used</param>
|
|
public static void WriteCompressed(Stream stream, ReadOnlySpan<byte> data, CompressionAlgorithm algorithm)
|
|
{
|
|
stream.WriteByte((byte)algorithm);
|
|
|
|
switch (algorithm)
|
|
{
|
|
case CompressionAlgorithm.None:
|
|
stream.Write(data);
|
|
break;
|
|
case CompressionAlgorithm.Deflate:
|
|
stream = new DeflateStream(stream, CompressionLevel.SmallestSize, true);
|
|
stream.Write(data);
|
|
stream.Dispose();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|