add methods Ryyjinx.Common EmbeddedResources and SteamUtils

This commit is contained in:
Jim Horvath 2024-02-22 20:22:44 -05:00 committed by jhorv
parent 27c50de93d
commit 0c7327cd52
2 changed files with 81 additions and 3 deletions

View file

@ -1,5 +1,6 @@
using Ryujinx.Common.Utilities;
using System;
using System.Buffers;
using System.IO;
using System.Linq;
using System.Reflection;
@ -23,6 +24,13 @@ namespace Ryujinx.Common
return Read(assembly, path);
}
public static IMemoryOwner<byte> ReadRentedMemory(string filename)
{
var (assembly, path) = ResolveManifestPath(filename);
return ReadRentedMemory(assembly, path);
}
public static Task<byte[]> ReadAsync(string filename)
{
var (assembly, path) = ResolveManifestPath(filename);
@ -41,6 +49,15 @@ namespace Ryujinx.Common
return StreamUtils.StreamToBytes(stream);
}
public static IMemoryOwner<byte> ReadRentedMemory(Assembly assembly, string filename)
{
using var stream = GetStream(assembly, filename);
return stream is null
? null
: StreamUtils.StreamToRentedMemory(stream);
}
public async static Task<byte[]> ReadAsync(Assembly assembly, string filename)
{
using var stream = GetStream(assembly, filename);

View file

@ -1,4 +1,6 @@
using Microsoft.IO;
using Ryujinx.Common.Memory;
using System.Buffers;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@ -9,12 +11,50 @@ namespace Ryujinx.Common.Utilities
{
public static byte[] StreamToBytes(Stream input)
{
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
using RecyclableMemoryStream output = StreamToRecyclableMemoryStream(input);
return output.ToArray();
}
input.CopyTo(stream);
public static IMemoryOwner<byte> StreamToRentedMemory(Stream input)
{
if (input is MemoryStream inputMemoryStream)
{
return MemoryStreamToRentedMemory(inputMemoryStream);
}
else if (input.CanSeek)
{
long bytesExpected = input.Length;
return stream.ToArray();
IMemoryOwner<byte> ownedMemory = ByteMemoryPool.Rent(bytesExpected);
var destSpan = ownedMemory.Memory.Span;
int totalBytesRead = 0;
while (totalBytesRead < bytesExpected)
{
int bytesRead = input.Read(destSpan[totalBytesRead..]);
if (bytesRead == 0)
{
ownedMemory.Dispose();
throw new IOException($"Tried reading {bytesExpected} but the stream closed after reading {totalBytesRead}.");
}
totalBytesRead += bytesRead;
}
return ownedMemory;
}
else
{
// If input is (non-seekable) then copy twice: first into a RecyclableMemoryStream, then to a rented IMemoryOwner<byte>.
using RecyclableMemoryStream output = StreamToRecyclableMemoryStream(input);
return MemoryStreamToRentedMemory(output);
}
}
public static async Task<byte[]> StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default)
@ -25,5 +65,26 @@ namespace Ryujinx.Common.Utilities
return stream.ToArray();
}
private static IMemoryOwner<byte> MemoryStreamToRentedMemory(MemoryStream input)
{
input.Position = 0;
IMemoryOwner<byte> ownedMemory = ByteMemoryPool.Rent(input.Length);
// Discard the return value because we assume reading a MemoryStream always succeeds completely.
_ = input.Read(ownedMemory.Memory.Span);
return ownedMemory;
}
private static RecyclableMemoryStream StreamToRecyclableMemoryStream(Stream input)
{
RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream();
input.CopyTo(stream);
return stream;
}
}
}