2021-04-14 11:28:43 +01:00
using Ryujinx.Common.Configuration.Hid.Controller ;
using Ryujinx.Common.Configuration.Hid.Keyboard ;
2023-03-21 22:41:19 +00:00
using Ryujinx.Common.Utilities ;
2021-04-14 11:28:43 +01:00
using System ;
using System.Text.Json ;
using System.Text.Json.Serialization ;
namespace Ryujinx.Common.Configuration.Hid
{
2023-03-21 22:41:19 +00:00
public class JsonInputConfigConverter : JsonConverter < InputConfig >
2021-04-14 11:28:43 +01:00
{
2023-03-21 22:41:19 +00:00
private static readonly InputConfigJsonSerializerContext SerializerContext = new ( JsonHelper . GetDefaultSerializerOptions ( ) ) ;
2021-04-14 11:28:43 +01:00
private static InputBackendType GetInputBackendType ( ref Utf8JsonReader reader )
{
// Temporary reader to get the backend type
Utf8JsonReader tempReader = reader ;
InputBackendType result = InputBackendType . Invalid ;
while ( tempReader . Read ( ) )
{
// NOTE: We scan all properties ignoring the depth entirely on purpose.
// The reason behind this is that we cannot track in a reliable way the depth of the object because Utf8JsonReader never emit the first TokenType == StartObject if the json start with an object.
// As such, this code will try to parse very field named "backend" to the correct enum.
if ( tempReader . TokenType = = JsonTokenType . PropertyName )
{
string propertyName = tempReader . GetString ( ) ;
if ( propertyName . Equals ( "backend" ) )
{
tempReader . Read ( ) ;
if ( tempReader . TokenType = = JsonTokenType . String )
{
string backendTypeRaw = tempReader . GetString ( ) ;
if ( ! Enum . TryParse ( backendTypeRaw , out result ) )
{
result = InputBackendType . Invalid ;
}
else
{
break ;
}
}
}
}
}
return result ;
}
public override InputConfig Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
{
InputBackendType backendType = GetInputBackendType ( ref reader ) ;
return backendType switch
{
2023-03-21 22:41:19 +00:00
InputBackendType . WindowKeyboard = > JsonSerializer . Deserialize ( ref reader , SerializerContext . StandardKeyboardInputConfig ) ,
InputBackendType . GamepadSDL2 = > JsonSerializer . Deserialize ( ref reader , SerializerContext . StandardControllerInputConfig ) ,
2021-04-14 11:28:43 +01:00
_ = > throw new InvalidOperationException ( $"Unknown backend type {backendType}" ) ,
} ;
}
public override void Write ( Utf8JsonWriter writer , InputConfig value , JsonSerializerOptions options )
{
switch ( value . Backend )
{
case InputBackendType . WindowKeyboard :
2023-03-21 22:41:19 +00:00
JsonSerializer . Serialize ( writer , value as StandardKeyboardInputConfig , SerializerContext . StandardKeyboardInputConfig ) ;
2021-04-14 11:28:43 +01:00
break ;
case InputBackendType . GamepadSDL2 :
2023-03-21 22:41:19 +00:00
JsonSerializer . Serialize ( writer , value as StandardControllerInputConfig , SerializerContext . StandardControllerInputConfig ) ;
2021-04-14 11:28:43 +01:00
break ;
default :
throw new ArgumentException ( $"Unknown backend type {value.Backend}" ) ;
}
}
}
}