aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Common/Utilities
diff options
context:
space:
mode:
authorAndrey Sukharev <SukharevAndrey@users.noreply.github.com>2023-03-22 01:41:19 +0300
committerGitHub <noreply@github.com>2023-03-21 19:41:19 -0300
commit4ce4299ca2a6b11332f2341c69f40efd7205282f (patch)
tree595805d7b0288157c9e4e6598ce89de39e16b76c /Ryujinx.Common/Utilities
parent17620d18db8d4a67e4b917596c760107d26fadc5 (diff)
Use source generated json serializers in order to improve code trimming (#4094)
* Use source generated json serializers in order to improve code trimming * Use strongly typed github releases model to fetch updates instead of raw Newtonsoft.Json parsing * Use separate model for LogEventArgs serialization * Make dynamic object formatter static. Fix string builder pooling. * Do not inherit json version of LogEventArgs from EventArgs * Fix extra space in object formatting * Write log json directly to stream instead of using buffer writer * Rebase fixes * Rebase fixes * Rebase fixes * Enforce block-scoped namespaces in the solution. Convert style for existing code * Apply suggestions from code review Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Rebase indent fix * Fix indent * Delete unnecessary json properties * Rebase fix * Remove overridden json property names as they are handled in the options * Apply suggestions from code review Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Use default json options in github api calls * Indentation and spacing fixes --------- Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Diffstat (limited to 'Ryujinx.Common/Utilities')
-rw-r--r--Ryujinx.Common/Utilities/CommonJsonContext.cs11
-rw-r--r--Ryujinx.Common/Utilities/JsonHelper.cs122
-rw-r--r--Ryujinx.Common/Utilities/TypedStringEnumConverter.cs34
3 files changed, 100 insertions, 67 deletions
diff --git a/Ryujinx.Common/Utilities/CommonJsonContext.cs b/Ryujinx.Common/Utilities/CommonJsonContext.cs
new file mode 100644
index 00000000..d7b3f78c
--- /dev/null
+++ b/Ryujinx.Common/Utilities/CommonJsonContext.cs
@@ -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
+ {
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Common/Utilities/JsonHelper.cs b/Ryujinx.Common/Utilities/JsonHelper.cs
index 36f39114..9a2d6f18 100644
--- a/Ryujinx.Common/Utilities/JsonHelper.cs
+++ b/Ryujinx.Common/Utilities/JsonHelper.cs
@@ -1,15 +1,62 @@
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Hid.Controller.Motion;
-using System.IO;
+using System.IO;
using System.Text;
using System.Text.Json;
-using System.Text.Json.Serialization;
+using System.Text.Json.Serialization.Metadata;
namespace Ryujinx.Common.Utilities
{
public class JsonHelper
{
- public static JsonNamingPolicy SnakeCase { get; }
+ 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
{
@@ -20,7 +67,7 @@ namespace Ryujinx.Common.Utilities
return name;
}
- StringBuilder builder = new StringBuilder();
+ StringBuilder builder = new();
for (int i = 0; i < name.Length; i++)
{
@@ -34,7 +81,7 @@ namespace Ryujinx.Common.Utilities
}
else
{
- builder.Append("_");
+ builder.Append('_');
builder.Append(char.ToLowerInvariant(c));
}
}
@@ -47,64 +94,5 @@ namespace Ryujinx.Common.Utilities
return builder.ToString();
}
}
-
- static JsonHelper()
- {
- SnakeCase = new SnakeCaseNamingPolicy();
- }
-
- public static JsonSerializerOptions GetDefaultSerializerOptions(bool prettyPrint = false)
- {
- JsonSerializerOptions options = new JsonSerializerOptions
- {
- DictionaryKeyPolicy = SnakeCase,
- PropertyNamingPolicy = SnakeCase,
- WriteIndented = prettyPrint,
- AllowTrailingCommas = true,
- ReadCommentHandling = JsonCommentHandling.Skip
- };
-
- options.Converters.Add(new JsonStringEnumConverter());
- options.Converters.Add(new JsonInputConfigConverter());
- options.Converters.Add(new JsonMotionConfigControllerConverter());
-
- return options;
- }
-
- public static T Deserialize<T>(Stream stream)
- {
- using (BinaryReader reader = new BinaryReader(stream))
- {
- return JsonSerializer.Deserialize<T>(reader.ReadBytes((int)(stream.Length - stream.Position)), GetDefaultSerializerOptions());
- }
- }
-
- public static T DeserializeFromFile<T>(string path)
- {
- return Deserialize<T>(File.ReadAllText(path));
- }
-
- public static T Deserialize<T>(string json)
- {
- return JsonSerializer.Deserialize<T>(json, GetDefaultSerializerOptions());
- }
-
- public static void Serialize<TValue>(Stream stream, TValue obj, bool prettyPrint = false)
- {
- using (BinaryWriter writer = new BinaryWriter(stream))
- {
- writer.Write(SerializeToUtf8Bytes(obj, prettyPrint));
- }
- }
-
- public static string Serialize<TValue>(TValue obj, bool prettyPrint = false)
- {
- return JsonSerializer.Serialize(obj, GetDefaultSerializerOptions(prettyPrint));
- }
-
- public static byte[] SerializeToUtf8Bytes<T>(T obj, bool prettyPrint = false)
- {
- return JsonSerializer.SerializeToUtf8Bytes(obj, GetDefaultSerializerOptions(prettyPrint));
- }
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.Common/Utilities/TypedStringEnumConverter.cs b/Ryujinx.Common/Utilities/TypedStringEnumConverter.cs
new file mode 100644
index 00000000..c0127dc4
--- /dev/null
+++ b/Ryujinx.Common/Utilities/TypedStringEnumConverter.cs
@@ -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());
+ }
+ }
+}