Move solution and projects to src

This commit is contained in:
TSR Berry 2023-04-08 01:22:00 +02:00 committed by Mary
parent cd124bda58
commit cee7121058
3466 changed files with 55 additions and 55 deletions

View file

@ -0,0 +1,60 @@
using System;
using System.Numerics;
namespace Ryujinx.Common
{
public static class BitUtils
{
public static T AlignUp<T>(T value, T size)
where T : IBinaryInteger<T>
{
return (value + (size - T.One)) & -size;
}
public static T AlignDown<T>(T value, T size)
where T : IBinaryInteger<T>
{
return value & -size;
}
public static T DivRoundUp<T>(T value, T dividend)
where T : IBinaryInteger<T>
{
return (value + (dividend - T.One)) / dividend;
}
public static int Pow2RoundUp(int value)
{
value--;
value |= (value >> 1);
value |= (value >> 2);
value |= (value >> 4);
value |= (value >> 8);
value |= (value >> 16);
return ++value;
}
public static int Pow2RoundDown(int value)
{
return BitOperations.IsPow2(value) ? value : Pow2RoundUp(value) >> 1;
}
public static long ReverseBits64(long value)
{
return (long)ReverseBits64((ulong)value);
}
private static ulong ReverseBits64(ulong value)
{
value = ((value & 0xaaaaaaaaaaaaaaaa) >> 1 ) | ((value & 0x5555555555555555) << 1 );
value = ((value & 0xcccccccccccccccc) >> 2 ) | ((value & 0x3333333333333333) << 2 );
value = ((value & 0xf0f0f0f0f0f0f0f0) >> 4 ) | ((value & 0x0f0f0f0f0f0f0f0f) << 4 );
value = ((value & 0xff00ff00ff00ff00) >> 8 ) | ((value & 0x00ff00ff00ff00ff) << 8 );
value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16);
return (value >> 32) | (value << 32);
}
}
}

View file

@ -0,0 +1,57 @@
using System.Numerics;
using System.Runtime.CompilerServices;
namespace Ryujinx.Common.Utilities
{
public static class BitfieldExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Extract<T>(this T value, int lsb) where T : IBinaryInteger<T>
{
int bitSize = Unsafe.SizeOf<T>() * 8;
lsb &= bitSize - 1;
return !T.IsZero((value >>> lsb) & T.One);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Extract<T>(this T value, int lsb, int length) where T : IBinaryInteger<T>
{
int bitSize = Unsafe.SizeOf<T>() * 8;
lsb &= bitSize - 1;
return (value >>> lsb) & (~T.Zero >>> (bitSize - length));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T ExtractSx<T>(this T value, int lsb, int length) where T : IBinaryInteger<T>
{
int bitSize = Unsafe.SizeOf<T>() * 8;
int shift = lsb & (bitSize - 1);
return (value << (bitSize - (shift + length))) >> (bitSize - length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Insert<T>(this T value, int lsb, bool toInsert) where T : IBinaryInteger<T>
{
int bitSize = Unsafe.SizeOf<T>() * 8;
lsb &= bitSize - 1;
T mask = T.One << lsb;
return (value & ~mask) | (toInsert ? mask : T.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Insert<T>(this T value, int lsb, int length, T toInsert) where T : IBinaryInteger<T>
{
int bitSize = Unsafe.SizeOf<T>() * 8;
lsb &= bitSize - 1;
T mask = (~T.Zero >>> (bitSize - length)) << lsb;
return (value & ~mask) | ((toInsert << lsb) & mask);
}
}
}

View file

@ -0,0 +1,59 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Common.Utilities
{
[DebuggerDisplay("{ToString()}")]
[StructLayout(LayoutKind.Sequential, Size = 16)]
public struct Buffer16
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1;
public byte this[int i]
{
get => Bytes[i];
set => Bytes[i] = value;
}
public Span<byte> Bytes => SpanHelpers.AsByteSpan(ref this);
// Prevent a defensive copy by changing the read-only in reference to a reference with Unsafe.AsRef()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Span<byte>(in Buffer16 value)
{
return SpanHelpers.AsByteSpan(ref Unsafe.AsRef(in value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlySpan<byte>(in Buffer16 value)
{
return SpanHelpers.AsReadOnlyByteSpan(ref Unsafe.AsRef(in value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T As<T>() where T : unmanaged
{
if (Unsafe.SizeOf<T>() > (uint)Unsafe.SizeOf<Buffer16>())
{
throw new ArgumentException();
}
return ref MemoryMarshal.GetReference(AsSpan<T>());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<T> AsSpan<T>() where T : unmanaged
{
return SpanHelpers.AsSpan<Buffer16, T>(ref this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ReadOnlySpan<T> AsReadOnlySpan<T>() where T : unmanaged
{
return SpanHelpers.AsReadOnlySpan<Buffer16, T>(ref Unsafe.AsRef(in this));
}
}
}

View file

@ -0,0 +1,11 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Ryujinx.Common.Utilities
{
[JsonSerializable(typeof(string[]), TypeInfoPropertyName = "StringArray")]
[JsonSerializable(typeof(Dictionary<string, string>), TypeInfoPropertyName = "StringDictionary")]
public partial class CommonJsonContext : JsonSerializerContext
{
}
}

View file

@ -0,0 +1,148 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Ryujinx.Common
{
public static class EmbeddedResources
{
private readonly static Assembly ResourceAssembly;
static EmbeddedResources()
{
ResourceAssembly = Assembly.GetAssembly(typeof(EmbeddedResources));
}
public static byte[] Read(string filename)
{
var (assembly, path) = ResolveManifestPath(filename);
return Read(assembly, path);
}
public static Task<byte[]> ReadAsync(string filename)
{
var (assembly, path) = ResolveManifestPath(filename);
return ReadAsync(assembly, path);
}
public static byte[] Read(Assembly assembly, string filename)
{
using (var stream = GetStream(assembly, filename))
{
if (stream == null)
{
return null;
}
return StreamUtils.StreamToBytes(stream);
}
}
public async static Task<byte[]> ReadAsync(Assembly assembly, string filename)
{
using (var stream = GetStream(assembly, filename))
{
if (stream == null)
{
return null;
}
return await StreamUtils.StreamToBytesAsync(stream);
}
}
public static string ReadAllText(string filename)
{
var (assembly, path) = ResolveManifestPath(filename);
return ReadAllText(assembly, path);
}
public static Task<string> ReadAllTextAsync(string filename)
{
var (assembly, path) = ResolveManifestPath(filename);
return ReadAllTextAsync(assembly, path);
}
public static string ReadAllText(Assembly assembly, string filename)
{
using (var stream = GetStream(assembly, filename))
{
if (stream == null)
{
return null;
}
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename)
{
using (var stream = GetStream(assembly, filename))
{
if (stream == null)
{
return null;
}
using (var reader = new StreamReader(stream))
{
return await reader.ReadToEndAsync();
}
}
}
public static Stream GetStream(string filename)
{
var (assembly, path) = ResolveManifestPath(filename);
return GetStream(assembly, path);
}
public static Stream GetStream(Assembly assembly, string filename)
{
var namespace_ = assembly.GetName().Name;
var manifestUri = namespace_ + "." + filename.Replace('/', '.');
var stream = assembly.GetManifestResourceStream(manifestUri);
return stream;
}
public static string[] GetAllAvailableResources(string path, string ext = "")
{
return ResolveManifestPath(path).Item1.GetManifestResourceNames()
.Where(r => r.EndsWith(ext))
.ToArray();
}
private static (Assembly, string) ResolveManifestPath(string filename)
{
var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length >= 2)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (assembly.GetName().Name == segments[0])
{
return (assembly, segments[1]);
}
}
}
return (ResourceAssembly, filename);
}
}
}

View file

@ -0,0 +1,90 @@
using System;
using System.Text;
namespace Ryujinx.Common
{
public static class HexUtils
{
private static readonly char[] HexChars = "0123456789ABCDEF".ToCharArray();
private const int HexTableColumnWidth = 8;
private const int HexTableColumnSpace = 3;
// Modified for Ryujinx
// Original by Pascal Ganaye - CPOL License
// https://www.codeproject.com/Articles/36747/Quick-and-Dirty-HexDump-of-a-Byte-Array
public static string HexTable(byte[] bytes, int bytesPerLine = 16)
{
if (bytes == null)
{
return "<null>";
}
int bytesLength = bytes.Length;
int firstHexColumn =
HexTableColumnWidth
+ HexTableColumnSpace;
int firstCharColumn = firstHexColumn
+ bytesPerLine * HexTableColumnSpace
+ (bytesPerLine - 1) / HexTableColumnWidth
+ 2;
int lineLength = firstCharColumn
+ bytesPerLine
+ Environment.NewLine.Length;
char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray();
int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
StringBuilder result = new StringBuilder(expectedLines * lineLength);
for (int i = 0; i < bytesLength; i += bytesPerLine)
{
line[0] = HexChars[(i >> 28) & 0xF];
line[1] = HexChars[(i >> 24) & 0xF];
line[2] = HexChars[(i >> 20) & 0xF];
line[3] = HexChars[(i >> 16) & 0xF];
line[4] = HexChars[(i >> 12) & 0xF];
line[5] = HexChars[(i >> 8) & 0xF];
line[6] = HexChars[(i >> 4) & 0xF];
line[7] = HexChars[(i >> 0) & 0xF];
int hexColumn = firstHexColumn;
int charColumn = firstCharColumn;
for (int j = 0; j < bytesPerLine; j++)
{
if (j > 0 && (j & 7) == 0)
{
hexColumn++;
}
if (i + j >= bytesLength)
{
line[hexColumn] = ' ';
line[hexColumn + 1] = ' ';
line[charColumn] = ' ';
}
else
{
byte b = bytes[i + j];
line[hexColumn] = HexChars[(b >> 4) & 0xF];
line[hexColumn + 1] = HexChars[b & 0xF];
line[charColumn] = (b < 32 ? '·' : (char)b);
}
hexColumn += 3;
charColumn++;
}
result.Append(line);
}
return result.ToString();
}
}
}

View file

@ -0,0 +1,98 @@
using System.IO;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
namespace Ryujinx.Common.Utilities
{
public class JsonHelper
{
private static readonly JsonNamingPolicy SnakeCasePolicy = new SnakeCaseNamingPolicy();
private const int DefaultFileWriteBufferSize = 4096;
/// <summary>
/// Creates new serializer options with default settings.
/// </summary>
/// <remarks>
/// It is REQUIRED for you to save returned options statically or as a part of static serializer context
/// in order to avoid performance issues. You can safely modify returned options for your case before storing.
/// </remarks>
public static JsonSerializerOptions GetDefaultSerializerOptions(bool indented = true)
{
JsonSerializerOptions options = new()
{
DictionaryKeyPolicy = SnakeCasePolicy,
PropertyNamingPolicy = SnakeCasePolicy,
WriteIndented = indented,
AllowTrailingCommas = true,
ReadCommentHandling = JsonCommentHandling.Skip
};
return options;
}
public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo)
{
return JsonSerializer.Serialize(value, typeInfo);
}
public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo)
{
return JsonSerializer.Deserialize(value, typeInfo);
}
public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo)
{
using FileStream file = File.Create(filePath, DefaultFileWriteBufferSize, FileOptions.WriteThrough);
JsonSerializer.Serialize(file, value, typeInfo);
}
public static T DeserializeFromFile<T>(string filePath, JsonTypeInfo<T> typeInfo)
{
using FileStream file = File.OpenRead(filePath);
return JsonSerializer.Deserialize(file, typeInfo);
}
public static void SerializeToStream<T>(Stream stream, T value, JsonTypeInfo<T> typeInfo)
{
JsonSerializer.Serialize(stream, value, typeInfo);
}
private class SnakeCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
if (string.IsNullOrEmpty(name))
{
return name;
}
StringBuilder builder = new();
for (int i = 0; i < name.Length; i++)
{
char c = name[i];
if (char.IsUpper(c))
{
if (i == 0 || char.IsUpper(name[i - 1]))
{
builder.Append(char.ToLowerInvariant(c));
}
else
{
builder.Append('_');
builder.Append(char.ToLowerInvariant(c));
}
}
else
{
builder.Append(c);
}
}
return builder.ToString();
}
}
}
}

View file

@ -0,0 +1,302 @@
using MsgPack;
using System;
using System.Text;
namespace Ryujinx.Common.Utilities
{
public static class MessagePackObjectFormatter
{
public static string ToString(this MessagePackObject obj, bool pretty)
{
if (pretty)
{
return Format(obj);
}
else
{
return obj.ToString();
}
}
public static string Format(MessagePackObject obj)
{
var builder = new IndentedStringBuilder();
FormatMsgPackObj(obj, builder);
return builder.ToString();
}
private static void FormatMsgPackObj(MessagePackObject obj, IndentedStringBuilder builder)
{
if (obj.IsMap || obj.IsDictionary)
{
FormatMsgPackMap(obj, builder);
}
else if (obj.IsArray || obj.IsList)
{
FormatMsgPackArray(obj, builder);
}
else if (obj.IsNil)
{
builder.Append("null");
}
else
{
var literal = obj.ToObject();
if (literal is String)
{
builder.AppendQuotedString(obj.AsStringUtf16());
}
else if (literal is byte[] byteArray)
{
FormatByteArray(byteArray, builder);
}
else if (literal is MessagePackExtendedTypeObject extObject)
{
builder.Append('{');
// Indent
builder.IncreaseIndent()
.AppendLine();
// Print TypeCode field
builder.AppendQuotedString("TypeCode")
.Append(": ")
.Append(extObject.TypeCode)
.AppendLine(",");
// Print Value field
builder.AppendQuotedString("Value")
.Append(": ");
FormatByteArrayAsString(extObject.GetBody(), builder, true);
// Unindent
builder.DecreaseIndent()
.AppendLine();
builder.Append('}');
}
else
{
builder.Append(literal);
}
}
}
private static void FormatByteArray(byte[] arr, IndentedStringBuilder builder)
{
builder.Append("[ ");
foreach (var b in arr)
{
builder.Append("0x");
builder.Append(ToHexChar(b >> 4));
builder.Append(ToHexChar(b & 0xF));
builder.Append(", ");
}
// Remove trailing comma
builder.Remove(builder.Length - 2, 2);
builder.Append(" ]");
}
private static void FormatByteArrayAsString(byte[] arr, IndentedStringBuilder builder, bool withPrefix)
{
builder.Append('"');
if (withPrefix)
{
builder.Append("0x");
}
foreach (var b in arr)
{
builder.Append(ToHexChar(b >> 4));
builder.Append(ToHexChar(b & 0xF));
}
builder.Append('"');
}
private static void FormatMsgPackMap(MessagePackObject obj, IndentedStringBuilder builder)
{
var map = obj.AsDictionary();
builder.Append('{');
// Indent
builder.IncreaseIndent()
.AppendLine();
foreach (var item in map)
{
FormatMsgPackObj(item.Key, builder);
builder.Append(": ");
FormatMsgPackObj(item.Value, builder);
builder.AppendLine(",");
}
// Remove the trailing new line and comma
builder.TrimLastLine()
.Remove(builder.Length - 1, 1);
// Unindent
builder.DecreaseIndent()
.AppendLine();
builder.Append('}');
}
private static void FormatMsgPackArray(MessagePackObject obj, IndentedStringBuilder builder)
{
var arr = obj.AsList();
builder.Append("[ ");
foreach (var item in arr)
{
FormatMsgPackObj(item, builder);
builder.Append(", ");
}
// Remove trailing comma
builder.Remove(builder.Length - 2, 2);
builder.Append(" ]");
}
private static char ToHexChar(int b)
{
if (b < 10)
{
return unchecked((char)('0' + b));
}
else
{
return unchecked((char)('A' + (b - 10)));
}
}
internal class IndentedStringBuilder
{
const string DefaultIndent = " ";
private int _indentCount = 0;
private int _newLineIndex = 0;
private StringBuilder _builder;
public string IndentString { get; set; } = DefaultIndent;
public IndentedStringBuilder(StringBuilder builder)
{
_builder = builder;
}
public IndentedStringBuilder()
: this(new StringBuilder())
{ }
public IndentedStringBuilder(string str)
: this(new StringBuilder(str))
{ }
public IndentedStringBuilder(int length)
: this(new StringBuilder(length))
{ }
public int Length { get => _builder.Length; }
public IndentedStringBuilder IncreaseIndent()
{
_indentCount++;
return this;
}
public IndentedStringBuilder DecreaseIndent()
{
_indentCount--;
return this;
}
public IndentedStringBuilder Append(char value)
{
_builder.Append(value);
return this;
}
public IndentedStringBuilder Append(string value)
{
_builder.Append(value);
return this;
}
public IndentedStringBuilder Append(object value)
{
this.Append(value.ToString());
return this;
}
public IndentedStringBuilder AppendQuotedString(string value)
{
_builder.Append('"');
_builder.Append(value);
_builder.Append('"');
return this;
}
public IndentedStringBuilder AppendLine()
{
_newLineIndex = _builder.Length;
_builder.AppendLine();
for (int i = 0; i < _indentCount; i++)
_builder.Append(IndentString);
return this;
}
public IndentedStringBuilder AppendLine(string value)
{
_builder.Append(value);
this.AppendLine();
return this;
}
public IndentedStringBuilder TrimLastLine()
{
_builder.Remove(_newLineIndex, _builder.Length - _newLineIndex);
return this;
}
public IndentedStringBuilder Remove(int startIndex, int length)
{
_builder.Remove(startIndex, length);
return this;
}
public override string ToString()
{
return _builder.ToString();
}
}
}
}

View file

@ -0,0 +1,66 @@
using System.Net.NetworkInformation;
namespace Ryujinx.Common.Utilities
{
public static class NetworkHelpers
{
private static (IPInterfaceProperties, UnicastIPAddressInformation) GetLocalInterface(NetworkInterface adapter, bool isPreferred)
{
IPInterfaceProperties properties = adapter.GetIPProperties();
if (isPreferred || (properties.GatewayAddresses.Count > 0 && properties.DnsAddresses.Count > 0))
{
foreach (UnicastIPAddressInformation info in properties.UnicastAddresses)
{
// Only accept an IPv4 address
if (info.Address.GetAddressBytes().Length == 4)
{
return (properties, info);
}
}
}
return (null, null);
}
public static (IPInterfaceProperties, UnicastIPAddressInformation) GetLocalInterface(string lanInterfaceId = "0")
{
if (!NetworkInterface.GetIsNetworkAvailable())
{
return (null, null);
}
IPInterfaceProperties targetProperties = null;
UnicastIPAddressInformation targetAddressInfo = null;
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
string guid = lanInterfaceId;
bool hasPreference = guid != "0";
foreach (NetworkInterface adapter in interfaces)
{
bool isPreferred = adapter.Id == guid;
// Ignore loopback and non IPv4 capable interface.
if (isPreferred || (targetProperties == null && adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback && adapter.Supports(NetworkInterfaceComponent.IPv4)))
{
(IPInterfaceProperties properties, UnicastIPAddressInformation info) = GetLocalInterface(adapter, isPreferred);
if (properties != null)
{
targetProperties = properties;
targetAddressInfo = info;
if (isPreferred || !hasPreference)
{
break;
}
}
}
}
return (targetProperties, targetAddressInfo);
}
}
}

View file

@ -0,0 +1,61 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Common.Utilities
{
public static class SpanHelpers
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> CreateSpan<T>(scoped ref T reference, int length)
{
return MemoryMarshal.CreateSpan(ref reference, length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(scoped ref T reference) where T : unmanaged
{
return CreateSpan(ref reference, 1);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<TSpan> AsSpan<TStruct, TSpan>(scoped ref TStruct reference)
where TStruct : unmanaged where TSpan : unmanaged
{
return CreateSpan(ref Unsafe.As<TStruct, TSpan>(ref reference),
Unsafe.SizeOf<TStruct>() / Unsafe.SizeOf<TSpan>());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> AsByteSpan<T>(scoped ref T reference) where T : unmanaged
{
return CreateSpan(ref Unsafe.As<T, byte>(ref reference), Unsafe.SizeOf<T>());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<T> CreateReadOnlySpan<T>(scoped ref T reference, int length)
{
return MemoryMarshal.CreateReadOnlySpan(ref reference, length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<T> AsReadOnlySpan<T>(scoped ref T reference) where T : unmanaged
{
return CreateReadOnlySpan(ref reference, 1);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<TSpan> AsReadOnlySpan<TStruct, TSpan>(scoped ref TStruct reference)
where TStruct : unmanaged where TSpan : unmanaged
{
return CreateReadOnlySpan(ref Unsafe.As<TStruct, TSpan>(ref reference),
Unsafe.SizeOf<TStruct>() / Unsafe.SizeOf<TSpan>());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<byte> AsReadOnlyByteSpan<T>(scoped ref T reference) where T : unmanaged
{
return CreateReadOnlySpan(ref Unsafe.As<T, byte>(ref reference), Unsafe.SizeOf<T>());
}
}
}

View file

@ -0,0 +1,31 @@
using Microsoft.IO;
using Ryujinx.Common.Memory;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Ryujinx.Common.Utilities
{
public static class StreamUtils
{
public static byte[] StreamToBytes(Stream input)
{
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream())
{
input.CopyTo(stream);
return stream.ToArray();
}
}
public static async Task<byte[]> StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default)
{
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream())
{
await input.CopyToAsync(stream, cancellationToken);
return stream.ToArray();
}
}
}
}

View file

@ -0,0 +1,34 @@
#nullable enable
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Ryujinx.Common.Utilities
{
/// <summary>
/// Specifies that value of <see cref="TEnum"/> will be serialized as string in JSONs
/// </summary>
/// <remarks>
/// Trimming friendly alternative to <see cref="JsonStringEnumConverter"/>.
/// Get rid of this converter if dotnet supports similar functionality out of the box.
/// </remarks>
/// <typeparam name="TEnum">Type of enum to serialize</typeparam>
public sealed class TypedStringEnumConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, Enum
{
public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var enumValue = reader.GetString();
if (string.IsNullOrEmpty(enumValue))
{
return default;
}
return Enum.Parse<TEnum>(enumValue);
}
public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
}

View file

@ -0,0 +1,18 @@
using System;
using System.Globalization;
namespace Ryujinx.Common.Utilities
{
public static class UInt128Utils
{
public static UInt128 FromHex(string hex)
{
return new UInt128(ulong.Parse(hex.AsSpan(0, 16), NumberStyles.HexNumber), ulong.Parse(hex.AsSpan(16), NumberStyles.HexNumber));
}
public static UInt128 CreateRandom()
{
return new UInt128((ulong)Random.Shared.NextInt64(), (ulong)Random.Shared.NextInt64());
}
}
}