diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs index d8c8ea568fd..1f33dedb905 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs @@ -196,28 +196,38 @@ public partial class VariantUtils if (typeof(GodotObject).IsAssignableFrom(typeof(T))) return CreateFromGodotObject(UnsafeAs(from)); - // `typeof(T).IsValueType` is optimized away - // `typeof(T).IsEnum` is NOT optimized away: https://github.com/dotnet/runtime/issues/67113 - // Fortunately, `typeof(System.Enum).IsAssignableFrom(typeof(T))` does the job! + // `typeof(T).IsEnum` is optimized away - if (typeof(T).IsValueType && typeof(System.Enum).IsAssignableFrom(typeof(T))) + if (typeof(T).IsEnum) { - // `Type.GetTypeCode(typeof(T).GetEnumUnderlyingType())` is not optimized away. - // Fortunately, `Unsafe.SizeOf()` works and is optimized away. - // We don't need to know whether it's signed or unsigned. + // `typeof(T).GetEnumUnderlyingType()` is optimized away - if (Unsafe.SizeOf() == 1) + var enumType = typeof(T).GetEnumUnderlyingType(); + + if (enumType == typeof(sbyte)) return CreateFromInt(UnsafeAs(from)); - if (Unsafe.SizeOf() == 2) + if (enumType == typeof(short)) return CreateFromInt(UnsafeAs(from)); - if (Unsafe.SizeOf() == 4) + if (enumType == typeof(int)) return CreateFromInt(UnsafeAs(from)); - if (Unsafe.SizeOf() == 8) + if (enumType == typeof(long)) return CreateFromInt(UnsafeAs(from)); + if (enumType == typeof(byte)) + return CreateFromInt(UnsafeAs(from)); + + if (enumType == typeof(ushort)) + return CreateFromInt(UnsafeAs(from)); + + if (enumType == typeof(uint)) + return CreateFromInt(UnsafeAs(from)); + + if (enumType == typeof(ulong)) + return CreateFromInt(UnsafeAs(from)); + throw UnsupportedType(); } @@ -387,28 +397,38 @@ public partial class VariantUtils if (typeof(GodotObject).IsAssignableFrom(typeof(T))) return (T)(object)ConvertToGodotObject(variant); - // `typeof(T).IsValueType` is optimized away - // `typeof(T).IsEnum` is NOT optimized away: https://github.com/dotnet/runtime/issues/67113 - // Fortunately, `typeof(System.Enum).IsAssignableFrom(typeof(T))` does the job! + // `typeof(T).IsEnum` is optimized away - if (typeof(T).IsValueType && typeof(System.Enum).IsAssignableFrom(typeof(T))) + if (typeof(T).IsEnum) { - // `Type.GetTypeCode(typeof(T).GetEnumUnderlyingType())` is not optimized away. - // Fortunately, `Unsafe.SizeOf()` works and is optimized away. - // We don't need to know whether it's signed or unsigned. + // `typeof(T).GetEnumUnderlyingType()` is optimized away - if (Unsafe.SizeOf() == 1) + var enumType = typeof(T).GetEnumUnderlyingType(); + + if (enumType == typeof(sbyte)) return UnsafeAsT(ConvertToInt8(variant)); - if (Unsafe.SizeOf() == 2) + if (enumType == typeof(short)) return UnsafeAsT(ConvertToInt16(variant)); - if (Unsafe.SizeOf() == 4) + if (enumType == typeof(int)) return UnsafeAsT(ConvertToInt32(variant)); - if (Unsafe.SizeOf() == 8) + if (enumType == typeof(long)) return UnsafeAsT(ConvertToInt64(variant)); + if (enumType == typeof(byte)) + return UnsafeAsT(ConvertToUInt8(variant)); + + if (enumType == typeof(ushort)) + return UnsafeAsT(ConvertToUInt16(variant)); + + if (enumType == typeof(uint)) + return UnsafeAsT(ConvertToUInt32(variant)); + + if (enumType == typeof(ulong)) + return UnsafeAsT(ConvertToUInt64(variant)); + throw UnsupportedType(); }