Files
sbox-public/engine/Sandbox.System/Translation.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

191 lines
3.7 KiB
C#

using System.Collections;
using System.Text.Json.Serialization;
namespace Sandbox;
/// <summary>
/// This isn't ideal, but it does what we want it to do. Kind of.
/// </summary>
internal static class Translation
{
internal static JsonSerializerOptions options;
static Translation()
{
options = new JsonSerializerOptions( JsonSerializerOptions.Default );
options.PropertyNameCaseInsensitive = true;
options.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString | System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals;
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault;
options.Converters.Add( new JsonStringEnumConverter( null, true ) );
}
internal static bool TryConvert( ref object value, Type targetType )
{
if ( TryConvert( value, targetType, out var converted ) )
{
value = converted;
return true;
}
return false;
}
internal static bool TryConvert( object from, System.Type targetType, out object convertedValue )
{
convertedValue = null;
//
// Old value is null
//
if ( from == null )
{
return true;
}
var fromT = from.GetType();
//
// Targetting Nullable? Work with the underlying type
//
if ( targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof( Nullable<> ) )
{
targetType = Nullable.GetUnderlyingType( targetType ) ?? targetType;
}
//
// Type compatible matches
//
if ( fromT == targetType || fromT.IsAssignableTo( targetType ) )
{
convertedValue = from;
return true;
}
//
// String
//
if ( targetType == typeof( string ) )
{
convertedValue = $"{from}";
return true;
}
//
// JsonElement
//
if ( from is JsonElement jse )
{
convertedValue = jse.Deserialize( targetType, options );
return true;
}
//
// Bool
//
if ( targetType == typeof( bool ) )
{
convertedValue = $"{from}".ToBool();
return true;
}
//
// Bool
//
if ( targetType.IsEnum )
{
convertedValue = System.Enum.Parse( targetType, from.ToString() );
return true;
}
//
// Float
//
if ( targetType == typeof( float ) )
{
if ( float.TryParse( from.ToString(), out var f ) )
{
convertedValue = f;
return true;
}
return false;
}
//
// Int
//
if ( targetType == typeof( int ) )
{
if ( from is string str )
{
convertedValue = str.ToInt();
return true;
}
convertedValue = Convert.ToInt32( from );
return true;
}
//
// List
//
if ( targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof( List<string> ).GetGenericTypeDefinition() )
{
if ( fromT.IsArray && fromT.GetElementType() == targetType.GenericTypeArguments[0] )
{
convertedValue = System.Activator.CreateInstance( targetType, new[] { from } );
return true;
}
}
//
// Array
//
if ( targetType.IsArray )
{
if ( from is IList list )
{
var a = Array.CreateInstance( fromT.GenericTypeArguments[0], list.Count );
list.CopyTo( a, 0 );
convertedValue = a;
return true;
}
}
//
// Implicit conversion
//
var op_Implicit = targetType.GetMethod( "op_Implicit", new[] { from.GetType() } );
if ( op_Implicit != null )
{
convertedValue = op_Implicit.Invoke( null, new[] { from } );
return true;
}
//
// convertable
//
if ( from is IConvertible )
{
try
{
var changedValue = System.Convert.ChangeType( from, targetType );
if ( changedValue is not null )
{
convertedValue = changedValue;
return true;
}
}
catch
{
Log.Trace( $"Couldn't convert {from} from its type to {targetType}" );
}
}
// TODO - serialize to json, deserialize from json
return false;
}
}