com.wallstop-studios.unity-helpers 2.0.0-rc80.4 → 2.0.0-rc80.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -12,142 +12,60 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
|
|
|
12
12
|
public static class EnumNameCache<T>
|
|
13
13
|
where T : struct, Enum
|
|
14
14
|
{
|
|
15
|
-
private
|
|
16
|
-
|
|
17
|
-
private static readonly bool UseDensePacking;
|
|
18
|
-
private static readonly int Min;
|
|
19
|
-
private static readonly string[] DenseNames;
|
|
20
|
-
private static readonly Dictionary<int, string> SparseNames;
|
|
15
|
+
private static readonly Dictionary<T, string> Names;
|
|
21
16
|
|
|
22
17
|
static EnumNameCache()
|
|
23
18
|
{
|
|
24
|
-
T[] values = Enum.GetValues(typeof(T)).
|
|
25
|
-
|
|
26
|
-
int
|
|
27
|
-
int max = intValues.Max();
|
|
28
|
-
int range = max - min + 1;
|
|
29
|
-
|
|
30
|
-
if (range <= MaxDenseRange)
|
|
31
|
-
{
|
|
32
|
-
UseDensePacking = true;
|
|
33
|
-
Min = min;
|
|
34
|
-
DenseNames = new string[range];
|
|
35
|
-
|
|
36
|
-
for (int i = 0; i < values.Length; i++)
|
|
37
|
-
{
|
|
38
|
-
int key = intValues[i] - min;
|
|
39
|
-
T value = values[i];
|
|
40
|
-
DenseNames[key] = value.ToString("G");
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
else
|
|
19
|
+
T[] values = Enum.GetValues(typeof(T)).OfType<T>().ToArray();
|
|
20
|
+
Names = new Dictionary<T, string>(values.Length);
|
|
21
|
+
for (int i = 0; i < values.Length; i++)
|
|
44
22
|
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
int key = Unsafe.As<T, int>(ref values[i]);
|
|
50
|
-
T value = values[i];
|
|
51
|
-
string name = value.ToString("G");
|
|
52
|
-
SparseNames.TryAdd(key, name);
|
|
53
|
-
}
|
|
23
|
+
T value = values[i];
|
|
24
|
+
string name = value.ToString("G");
|
|
25
|
+
Names.TryAdd(value, name);
|
|
54
26
|
}
|
|
55
27
|
}
|
|
56
28
|
|
|
57
29
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
58
30
|
public static string ToCachedName(T value)
|
|
59
31
|
{
|
|
60
|
-
|
|
61
|
-
if (UseDensePacking)
|
|
32
|
+
if (Names.TryGetValue(value, out string name))
|
|
62
33
|
{
|
|
63
|
-
|
|
64
|
-
if ((uint)idx < (uint)DenseNames!.Length)
|
|
65
|
-
{
|
|
66
|
-
return DenseNames[idx];
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
else
|
|
70
|
-
{
|
|
71
|
-
if (SparseNames!.TryGetValue(key, out string name))
|
|
72
|
-
{
|
|
73
|
-
return name;
|
|
74
|
-
}
|
|
34
|
+
return name;
|
|
75
35
|
}
|
|
76
36
|
|
|
77
|
-
return value.ToString();
|
|
37
|
+
return value.ToString("G");
|
|
78
38
|
}
|
|
79
39
|
}
|
|
80
40
|
|
|
81
41
|
public static class EnumDisplayNameCache<T>
|
|
82
42
|
where T : struct, Enum
|
|
83
43
|
{
|
|
84
|
-
private
|
|
85
|
-
|
|
86
|
-
private static readonly bool UseDensePacking;
|
|
87
|
-
private static readonly int Min;
|
|
88
|
-
private static readonly string[] DenseNames;
|
|
89
|
-
private static readonly Dictionary<int, string> SparseNames;
|
|
44
|
+
private static readonly Dictionary<T, string> Names;
|
|
90
45
|
|
|
91
46
|
static EnumDisplayNameCache()
|
|
92
47
|
{
|
|
93
48
|
Type type = typeof(T);
|
|
94
49
|
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
|
|
95
|
-
|
|
96
|
-
int[] intValues = values.Select(v => Unsafe.As<T, int>(ref v)).ToArray();
|
|
97
|
-
int min = intValues.Min();
|
|
98
|
-
int max = intValues.Max();
|
|
99
|
-
int range = max - min + 1;
|
|
50
|
+
Names = new Dictionary<T, string>(fields.Length);
|
|
100
51
|
|
|
101
|
-
|
|
52
|
+
for (int i = 0; i < fields.Length; i++)
|
|
102
53
|
{
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
int key = intValues[i] - min;
|
|
110
|
-
FieldInfo field = fields[i];
|
|
111
|
-
string name = field.IsAttributeDefined(out EnumDisplayNameAttribute displayName)
|
|
112
|
-
? displayName.DisplayName
|
|
113
|
-
: field.Name;
|
|
114
|
-
DenseNames[key] = name;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
else
|
|
118
|
-
{
|
|
119
|
-
UseDensePacking = false;
|
|
120
|
-
SparseNames = new Dictionary<int, string>(fields.Length);
|
|
121
|
-
for (int i = 0; i < fields.Length; i++)
|
|
122
|
-
{
|
|
123
|
-
int key = Unsafe.As<T, int>(ref values[i]);
|
|
124
|
-
FieldInfo field = fields[i];
|
|
125
|
-
string name = field.IsAttributeDefined(out EnumDisplayNameAttribute displayName)
|
|
126
|
-
? displayName.DisplayName
|
|
127
|
-
: field.Name;
|
|
128
|
-
SparseNames.TryAdd(key, name);
|
|
129
|
-
}
|
|
54
|
+
FieldInfo field = fields[i];
|
|
55
|
+
string name = field.IsAttributeDefined(out EnumDisplayNameAttribute displayName)
|
|
56
|
+
? displayName.DisplayName
|
|
57
|
+
: field.Name;
|
|
58
|
+
T value = (T)field.GetValue(null);
|
|
59
|
+
Names.TryAdd(value, name);
|
|
130
60
|
}
|
|
131
61
|
}
|
|
132
62
|
|
|
133
63
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
134
64
|
public static string ToDisplayName(T value)
|
|
135
65
|
{
|
|
136
|
-
|
|
137
|
-
if (UseDensePacking)
|
|
66
|
+
if (Names.TryGetValue(value, out string name))
|
|
138
67
|
{
|
|
139
|
-
|
|
140
|
-
if ((uint)idx < (uint)DenseNames!.Length)
|
|
141
|
-
{
|
|
142
|
-
return DenseNames[idx];
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
else
|
|
146
|
-
{
|
|
147
|
-
if (SparseNames!.TryGetValue(key, out string name))
|
|
148
|
-
{
|
|
149
|
-
return name;
|
|
150
|
-
}
|
|
68
|
+
return name;
|
|
151
69
|
}
|
|
152
70
|
|
|
153
71
|
return value.ToString();
|
|
@@ -160,9 +78,15 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
|
|
|
160
78
|
public static bool HasFlagNoAlloc<T>(this T value, T flag)
|
|
161
79
|
where T : unmanaged, Enum
|
|
162
80
|
{
|
|
163
|
-
ulong valueUnderlying = GetUInt64(value);
|
|
164
|
-
ulong flagUnderlying = GetUInt64(flag);
|
|
165
|
-
|
|
81
|
+
ulong? valueUnderlying = GetUInt64(value);
|
|
82
|
+
ulong? flagUnderlying = GetUInt64(flag);
|
|
83
|
+
if (valueUnderlying == null || flagUnderlying == null)
|
|
84
|
+
{
|
|
85
|
+
// Fallback for unsupported enum sizes
|
|
86
|
+
return value.HasFlag(flag);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return (valueUnderlying.Value & flagUnderlying.Value) == flagUnderlying.Value;
|
|
166
90
|
}
|
|
167
91
|
|
|
168
92
|
public static string ToDisplayName<T>(this T value)
|
|
@@ -190,23 +114,24 @@ namespace WallstopStudios.UnityHelpers.Core.Extension
|
|
|
190
114
|
}
|
|
191
115
|
|
|
192
116
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
193
|
-
private static
|
|
117
|
+
private static ulong? GetUInt64<T>(T value)
|
|
194
118
|
where T : unmanaged
|
|
195
119
|
{
|
|
196
|
-
|
|
197
|
-
Works because T is constrained to unmanaged, so it's safe to reinterpret
|
|
198
|
-
All enums are value types and have a fixed size
|
|
199
|
-
*/
|
|
200
|
-
return sizeof(T) switch
|
|
120
|
+
try
|
|
201
121
|
{
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
122
|
+
return Unsafe.SizeOf<T>() switch
|
|
123
|
+
{
|
|
124
|
+
1 => Unsafe.As<T, byte>(ref value),
|
|
125
|
+
2 => Unsafe.As<T, ushort>(ref value),
|
|
126
|
+
4 => Unsafe.As<T, uint>(ref value),
|
|
127
|
+
8 => Unsafe.As<T, ulong>(ref value),
|
|
128
|
+
_ => null,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
catch
|
|
132
|
+
{
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
210
135
|
}
|
|
211
136
|
}
|
|
212
137
|
}
|
|
@@ -2,6 +2,7 @@ namespace WallstopStudios.UnityHelpers.Tests.Extensions
|
|
|
2
2
|
{
|
|
3
3
|
using NUnit.Framework;
|
|
4
4
|
using UnityEngine.TestTools.Constraints;
|
|
5
|
+
using WallstopStudios.UnityHelpers.Core.Attributes;
|
|
5
6
|
using WallstopStudios.UnityHelpers.Core.Extension;
|
|
6
7
|
using Is = NUnit.Framework.Is;
|
|
7
8
|
|
|
@@ -26,8 +27,14 @@ namespace WallstopStudios.UnityHelpers.Tests.Extensions
|
|
|
26
27
|
private enum SmallTestEnum : short
|
|
27
28
|
{
|
|
28
29
|
None = 0,
|
|
30
|
+
|
|
31
|
+
[EnumDisplayName("TestFirst")]
|
|
29
32
|
First = 1 << 0,
|
|
33
|
+
|
|
34
|
+
[EnumDisplayName("TestSecond")]
|
|
30
35
|
Second = 1 << 1,
|
|
36
|
+
|
|
37
|
+
[EnumDisplayName("TestThird")]
|
|
31
38
|
Third = 1 << 2,
|
|
32
39
|
}
|
|
33
40
|
|
|
@@ -39,6 +46,24 @@ namespace WallstopStudios.UnityHelpers.Tests.Extensions
|
|
|
39
46
|
Third = 1 << 2,
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
[Test]
|
|
50
|
+
public void DisplayName()
|
|
51
|
+
{
|
|
52
|
+
Assert.AreEqual("None", SmallTestEnum.None.ToDisplayName());
|
|
53
|
+
Assert.AreEqual("TestFirst", SmallTestEnum.First.ToDisplayName());
|
|
54
|
+
Assert.AreEqual("TestSecond", SmallTestEnum.Second.ToDisplayName());
|
|
55
|
+
Assert.AreEqual("TestThird", SmallTestEnum.Third.ToDisplayName());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
[Test]
|
|
59
|
+
public void CachedName()
|
|
60
|
+
{
|
|
61
|
+
Assert.AreEqual("None", SmallTestEnum.None.ToCachedName());
|
|
62
|
+
Assert.AreEqual("First", SmallTestEnum.First.ToCachedName());
|
|
63
|
+
Assert.AreEqual("Second", SmallTestEnum.Second.ToCachedName());
|
|
64
|
+
Assert.AreEqual("Third", SmallTestEnum.Third.ToCachedName());
|
|
65
|
+
}
|
|
66
|
+
|
|
42
67
|
[Test]
|
|
43
68
|
public void HasFlagNoAlloc()
|
|
44
69
|
{
|
package/package.json
CHANGED