-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEnumExtension.cs
130 lines (118 loc) · 6.3 KB
/
EnumExtension.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using System;
using System.ComponentModel;
using Unity.Collections.LowLevel.Unsafe;
// https://github.com/dotnet/csharplang/discussions/1993#discussioncomment-104840
namespace BAStudio.StatePattern
{
public static class EnumExtension
{
// size-specific version
public static TInt AsInteger<TEnum, TInt>(this TEnum enumValue)
where TEnum : unmanaged, Enum
where TInt : unmanaged
{
if (UnsafeUtility.SizeOf<TEnum>() != UnsafeUtility.SizeOf<TInt>()) throw new Exception("Underlying type size mismatch");
TInt value = UnsafeUtility.As<TEnum, TInt>(ref enumValue);
return value;
}
// long version
public static long AsInt64<TEnum>(this TEnum enumValue)
where TEnum : unmanaged, Enum
{
long value;
if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<long>()) value = UnsafeUtility.As<TEnum, long>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<int>()) value = UnsafeUtility.As<TEnum, int>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<short>()) value = UnsafeUtility.As<TEnum, short>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<sbyte>()) value = UnsafeUtility.As<TEnum, sbyte>(ref enumValue);
else throw new Exception("Underlying type size mismatch");
return value;
}
// int version
public static int AsInt32<TEnum>(this TEnum enumValue)
where TEnum : unmanaged, Enum
{
int value;
if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<int>()) value = UnsafeUtility.As<TEnum, int>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<short>()) value = UnsafeUtility.As<TEnum, short>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<sbyte>()) value = UnsafeUtility.As<TEnum, sbyte>(ref enumValue);
else throw new Exception("Underlying type size mismatch");
return value;
}
// short version
public static short AsInt16<TEnum>(this TEnum enumValue)
where TEnum : unmanaged, Enum
{
short value;
if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<short>()) value = UnsafeUtility.As<TEnum, short>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<sbyte>()) value = UnsafeUtility.As<TEnum, sbyte>(ref enumValue);
else throw new Exception("Underlying type size mismatch");
return value;
}
// sbyte version
public static sbyte AsInt8<TEnum>(this TEnum enumValue)
where TEnum : unmanaged, Enum
{
sbyte value;
if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<sbyte>()) value = UnsafeUtility.As<TEnum, sbyte>(ref enumValue);
else throw new Exception("Underlying type size mismatch");
return value;
}
// ulong version
public static ulong AsUInt64<TEnum>(this TEnum enumValue)
where TEnum : unmanaged, Enum
{
ulong value;
if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<ulong>()) value = UnsafeUtility.As<TEnum, ulong>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<uint>()) value = UnsafeUtility.As<TEnum, uint>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<ushort>()) value = UnsafeUtility.As<TEnum, ushort>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<byte>()) value = UnsafeUtility.As<TEnum, byte>(ref enumValue);
else throw new Exception("Underlying type size mismatch");
return value;
}
// uint version
public static uint AsUInt32<TEnum>(this TEnum enumValue)
where TEnum : unmanaged, Enum
{
uint value;
if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<uint>()) value = UnsafeUtility.As<TEnum, uint>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<ushort>()) value = UnsafeUtility.As<TEnum, ushort>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<byte>()) value = UnsafeUtility.As<TEnum, byte>(ref enumValue);
else throw new Exception("Underlying type size mismatch");
return value;
}
// ushort version
public static ushort AsUInt16<TEnum>(this TEnum enumValue)
where TEnum : unmanaged, Enum
{
ushort value;
if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<ushort>()) value = UnsafeUtility.As<TEnum, ushort>(ref enumValue);
else if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<byte>()) value = UnsafeUtility.As<TEnum, byte>(ref enumValue);
else throw new Exception("Underlying type size mismatch");
return value;
}
// byte version
public static byte AsUInt8<TEnum>(this TEnum enumValue)
where TEnum : unmanaged, Enum
{
byte value;
if (UnsafeUtility.SizeOf<TEnum>() == UnsafeUtility.SizeOf<byte>()) value = UnsafeUtility.As<TEnum, byte>(ref enumValue);
else throw new Exception("Underlying type size mismatch");
return value;
}
/// <summary>
///
/// **Warning: The method explicitly cast the values to TInt.**
/// </summary>
/// <typeparam name="TEnum"></typeparam>
/// <typeparam name="TInt"></typeparam>
/// <returns></returns>
public static (TInt min, TInt max) MinMax<TEnum, TInt>() where TEnum : unmanaged, Enum where TInt : unmanaged
{
var valueMap = System.Enum.GetValues(typeof(TEnum));
if (valueMap.Length == 0) throw new InvalidEnumArgumentException("Nothing is defined! At least one item must be defined for the enum.");
return ((TInt) valueMap.GetValue(0), (TInt) valueMap.GetValue(valueMap.Length - 1));
}
public static (int min, int max) MinMaxInt<TEnum>() where TEnum : unmanaged, Enum
=> MinMax<TEnum, int>();
}
}