Skip to content

Commit ec8a9a5

Browse files
committed
Add support for Flags, fix unsafe conversions
1 parent bc69fb9 commit ec8a9a5

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

Runtime/Commons.cs

+62
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Reflection;
4+
using System.Runtime.InteropServices;
35
#if UNITY_5_3_OR_NEWER
46
using Unity.Collections.LowLevel.Unsafe;
57
#endif
@@ -71,6 +73,10 @@ public static int EnumToInt<T>(T value) where T : struct, Enum
7173
#if UNITY_5_3_OR_NEWER
7274
return UnsafeUtility.EnumToInt(value);
7375
#elif NETCOREAPP3_0_OR_GREATER || NET5_0_OR_GREATER
76+
if (EnumMetadata<T>.SizeOf == sizeof(long))
77+
{
78+
return (int) Unsafe.As<T, long>(ref value);
79+
}
7480
return Unsafe.As<T, int>(ref value);
7581
#else
7682
return Convert.ToInt32(value);
@@ -80,12 +86,68 @@ public static int EnumToInt<T>(T value) where T : struct, Enum
8086
public static T IntToEnum<T>(int value) where T : Enum
8187
{
8288
#if UNITY_5_3_OR_NEWER
89+
if (EnumMetadata<T>.SizeOf == sizeof(long))
90+
{
91+
var longValue = (long) value;
92+
return UnsafeUtility.As<long, T>(ref longValue);
93+
}
8394
return UnsafeUtility.As<int, T>(ref value);
8495
#elif NETCOREAPP3_0_OR_GREATER || NET5_0_OR_GREATER
96+
if (EnumMetadata<T>.SizeOf == sizeof(long))
97+
{
98+
var longValue = (long) value;
99+
return Unsafe.As<long, T>(ref longValue);
100+
}
85101
return Unsafe.As<int, T>(ref value);
86102
#else
87103
return (T) Enum.ToObject(typeof(T), value);
88104
#endif
89105
}
106+
107+
public static long EnumToLong<T>(T value) where T : struct, Enum
108+
{
109+
#if UNITY_5_3_OR_NEWER
110+
if (EnumMetadata<T>.SizeOf == sizeof(long))
111+
{
112+
return UnsafeUtility.As<T, long>(ref value);
113+
}
114+
return UnsafeUtility.EnumToInt(value);
115+
#elif NETCOREAPP3_0_OR_GREATER || NET5_0_OR_GREATER
116+
if (EnumMetadata<T>.SizeOf == sizeof(long))
117+
{
118+
return Unsafe.As<T, long>(ref value);
119+
}
120+
return Unsafe.As<T, int>(ref value);
121+
#else
122+
return Convert.ToInt64(value);
123+
#endif
124+
}
125+
126+
public static T LongToEnum<T>(long value) where T : Enum
127+
{
128+
#if UNITY_5_3_OR_NEWER
129+
if (EnumMetadata<T>.SizeOf == sizeof(long))
130+
{
131+
return UnsafeUtility.As<long, T>(ref value);
132+
}
133+
var intValue = (int) value;
134+
return UnsafeUtility.As<int, T>(ref intValue);
135+
#elif NETCOREAPP3_0_OR_GREATER || NET5_0_OR_GREATER
136+
if (EnumMetadata<T>.SizeOf == sizeof(long))
137+
{
138+
return Unsafe.As<long, T>(ref value);
139+
}
140+
var intValue = (int) value;
141+
return Unsafe.As<int, T>(ref intValue);
142+
#else
143+
return (T) Enum.ToObject(typeof(T), value);
144+
#endif
145+
}
146+
}
147+
148+
public static class EnumMetadata<T> where T : Enum
149+
{
150+
public static int SizeOf = Marshal.SizeOf(Enum.GetUnderlyingType(typeof(T)));
151+
public static bool HasFlags = typeof(T).IsDefined(typeof(FlagsAttribute));
90152
}
91153
}

Runtime/EnumBitMask32.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ public IEnumerator<T> GetEnumerator()
127127
{
128128
foreach (var bitIndex in Commons.EnumerateSetBits(_data))
129129
{
130-
yield return Commons.IntToEnum<T>(bitIndex);
130+
var value = EnumMetadata<T>.HasFlags ? 1 << bitIndex : bitIndex;
131+
yield return Commons.IntToEnum<T>(value);
131132
}
132133
}
133134

@@ -149,6 +150,10 @@ public bool Equals(EnumBitMask32<T> other)
149150

150151
private static int GetIntBitMask(T data)
151152
{
153+
if (EnumMetadata<T>.HasFlags)
154+
{
155+
return Commons.EnumToInt(data);
156+
}
152157
Contract.Requires(Commons.EnumToInt(data) < 32);
153158
return 1 << Commons.EnumToInt(data);
154159
}

Runtime/EnumBitMask64.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ public IEnumerator<T> GetEnumerator()
127127
{
128128
foreach (var bitIndex in Commons.EnumerateSetBits(_data))
129129
{
130-
yield return Commons.IntToEnum<T>(bitIndex);
130+
var value = EnumMetadata<T>.HasFlags ? 1L << bitIndex : bitIndex;
131+
yield return Commons.LongToEnum<T>(value);
131132
}
132133
}
133134

@@ -149,6 +150,10 @@ public bool Equals(EnumBitMask64<T> other)
149150

150151
private static long GetLongBitMask(T data)
151152
{
153+
if (EnumMetadata<T>.HasFlags)
154+
{
155+
return Commons.EnumToLong(data);
156+
}
152157
Contract.Requires(Commons.EnumToInt(data) < 64);
153158
return 1L << Commons.EnumToInt(data);
154159
}

0 commit comments

Comments
 (0)