com.wallstop-studios.unity-helpers 2.0.0-rc46 → 2.0.0-rc47
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.
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
namespace UnityHelpers.Core.Extension
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Runtime.CompilerServices;
|
|
5
|
+
|
|
6
|
+
public static class EnumExtensions
|
|
7
|
+
{
|
|
8
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
9
|
+
public static bool HasFlagNoAlloc<T>(this T value, T flag)
|
|
10
|
+
where T : unmanaged, Enum
|
|
11
|
+
{
|
|
12
|
+
ulong valueUnderlying = GetUInt64(value);
|
|
13
|
+
ulong flagUnderlying = GetUInt64(flag);
|
|
14
|
+
return (valueUnderlying & flagUnderlying) == flagUnderlying;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
18
|
+
private static unsafe ulong GetUInt64<T>(T value)
|
|
19
|
+
where T : unmanaged
|
|
20
|
+
{
|
|
21
|
+
/*
|
|
22
|
+
Works because T is constrained to unmanaged, so it's safe to reinterpret
|
|
23
|
+
All enums are value types and have a fixed size
|
|
24
|
+
*/
|
|
25
|
+
return sizeof(T) switch
|
|
26
|
+
{
|
|
27
|
+
1 => *(byte*)&value,
|
|
28
|
+
2 => *(ushort*)&value,
|
|
29
|
+
4 => *(uint*)&value,
|
|
30
|
+
8 => *(ulong*)&value,
|
|
31
|
+
_ => throw new ArgumentException(
|
|
32
|
+
$"Unsupported enum size: {sizeof(T)} for type {typeof(T)}"
|
|
33
|
+
),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
namespace UnityHelpers.Tests.Extensions
|
|
2
|
+
{
|
|
3
|
+
using Core.Extension;
|
|
4
|
+
using NUnit.Framework;
|
|
5
|
+
using UnityEngine.TestTools.Constraints;
|
|
6
|
+
using Is = NUnit.Framework.Is;
|
|
7
|
+
|
|
8
|
+
public sealed class EnumExtensionTests
|
|
9
|
+
{
|
|
10
|
+
private enum TestEnum
|
|
11
|
+
{
|
|
12
|
+
None = 0,
|
|
13
|
+
First = 1 << 0,
|
|
14
|
+
Second = 1 << 1,
|
|
15
|
+
Third = 1 << 2,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private enum TinyTestEnum : byte
|
|
19
|
+
{
|
|
20
|
+
None = 0,
|
|
21
|
+
First = 1 << 0,
|
|
22
|
+
Second = 1 << 1,
|
|
23
|
+
Third = 1 << 2,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private enum SmallTestEnum : short
|
|
27
|
+
{
|
|
28
|
+
None = 0,
|
|
29
|
+
First = 1 << 0,
|
|
30
|
+
Second = 1 << 1,
|
|
31
|
+
Third = 1 << 2,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private enum BigTestEnum : long
|
|
35
|
+
{
|
|
36
|
+
None = 0,
|
|
37
|
+
First = 1 << 0,
|
|
38
|
+
Second = 1 << 1,
|
|
39
|
+
Third = 1 << 2,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
[Test]
|
|
43
|
+
public void HasFlagNoAlloc()
|
|
44
|
+
{
|
|
45
|
+
Assert.IsTrue(TestEnum.First.HasFlagNoAlloc(TestEnum.First));
|
|
46
|
+
Assert.IsFalse(TestEnum.First.HasFlagNoAlloc(TestEnum.Second));
|
|
47
|
+
Assert.IsTrue((TestEnum.First | TestEnum.Second).HasFlagNoAlloc(TestEnum.First));
|
|
48
|
+
Assert.IsTrue((TestEnum.First | TestEnum.Second).HasFlagNoAlloc(TestEnum.Second));
|
|
49
|
+
Assert.IsFalse((TestEnum.First | TestEnum.Second).HasFlagNoAlloc(TestEnum.Third));
|
|
50
|
+
Assert.IsFalse(TestEnum.First.HasFlagNoAlloc((TestEnum.First | TestEnum.Second)));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
[Test]
|
|
54
|
+
public void HasFlagNoAllocTiny()
|
|
55
|
+
{
|
|
56
|
+
Assert.IsTrue(TinyTestEnum.First.HasFlagNoAlloc(TinyTestEnum.First));
|
|
57
|
+
Assert.IsFalse(TinyTestEnum.First.HasFlagNoAlloc(TinyTestEnum.Second));
|
|
58
|
+
Assert.IsTrue(
|
|
59
|
+
(TinyTestEnum.First | TinyTestEnum.Second).HasFlagNoAlloc(TinyTestEnum.First)
|
|
60
|
+
);
|
|
61
|
+
Assert.IsTrue(
|
|
62
|
+
(TinyTestEnum.First | TinyTestEnum.Second).HasFlagNoAlloc(TinyTestEnum.Second)
|
|
63
|
+
);
|
|
64
|
+
Assert.IsFalse(
|
|
65
|
+
(TinyTestEnum.First | TinyTestEnum.Second).HasFlagNoAlloc(TinyTestEnum.Third)
|
|
66
|
+
);
|
|
67
|
+
Assert.IsFalse(
|
|
68
|
+
TinyTestEnum.First.HasFlagNoAlloc((TinyTestEnum.First | TinyTestEnum.Second))
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
[Test]
|
|
73
|
+
public void HasFlagNoAllocSmall()
|
|
74
|
+
{
|
|
75
|
+
Assert.IsTrue(SmallTestEnum.First.HasFlagNoAlloc(SmallTestEnum.First));
|
|
76
|
+
Assert.IsFalse(SmallTestEnum.First.HasFlagNoAlloc(SmallTestEnum.Second));
|
|
77
|
+
Assert.IsTrue(
|
|
78
|
+
(SmallTestEnum.First | SmallTestEnum.Second).HasFlagNoAlloc(SmallTestEnum.First)
|
|
79
|
+
);
|
|
80
|
+
Assert.IsTrue(
|
|
81
|
+
(SmallTestEnum.First | SmallTestEnum.Second).HasFlagNoAlloc(SmallTestEnum.Second)
|
|
82
|
+
);
|
|
83
|
+
Assert.IsFalse(
|
|
84
|
+
(SmallTestEnum.First | SmallTestEnum.Second).HasFlagNoAlloc(SmallTestEnum.Third)
|
|
85
|
+
);
|
|
86
|
+
Assert.IsFalse(
|
|
87
|
+
SmallTestEnum.First.HasFlagNoAlloc((SmallTestEnum.First | SmallTestEnum.Second))
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
[Test]
|
|
92
|
+
public void HasFlagNoAllocBig()
|
|
93
|
+
{
|
|
94
|
+
Assert.IsTrue(BigTestEnum.First.HasFlagNoAlloc(BigTestEnum.First));
|
|
95
|
+
Assert.IsFalse(BigTestEnum.First.HasFlagNoAlloc(BigTestEnum.Second));
|
|
96
|
+
Assert.IsTrue(
|
|
97
|
+
(BigTestEnum.First | BigTestEnum.Second).HasFlagNoAlloc(BigTestEnum.First)
|
|
98
|
+
);
|
|
99
|
+
Assert.IsTrue(
|
|
100
|
+
(BigTestEnum.First | BigTestEnum.Second).HasFlagNoAlloc(BigTestEnum.Second)
|
|
101
|
+
);
|
|
102
|
+
Assert.IsFalse(
|
|
103
|
+
(BigTestEnum.First | BigTestEnum.Second).HasFlagNoAlloc(BigTestEnum.Third)
|
|
104
|
+
);
|
|
105
|
+
Assert.IsFalse(
|
|
106
|
+
BigTestEnum.First.HasFlagNoAlloc((BigTestEnum.First | BigTestEnum.Second))
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
[Test]
|
|
111
|
+
public void HasFlagsNoAllocDoesNotAlloc()
|
|
112
|
+
{
|
|
113
|
+
Assert.That(
|
|
114
|
+
() =>
|
|
115
|
+
{
|
|
116
|
+
TestEnum.First.HasFlagNoAlloc(TestEnum.First);
|
|
117
|
+
TinyTestEnum.First.HasFlagNoAlloc(TinyTestEnum.First);
|
|
118
|
+
BigTestEnum.First.HasFlagNoAlloc(BigTestEnum.First);
|
|
119
|
+
|
|
120
|
+
TestEnum.First.HasFlagNoAlloc(TestEnum.Second);
|
|
121
|
+
TinyTestEnum.First.HasFlagNoAlloc(TinyTestEnum.Second);
|
|
122
|
+
BigTestEnum.First.HasFlagNoAlloc(BigTestEnum.Second);
|
|
123
|
+
},
|
|
124
|
+
Is.Not.AllocatingGCMemory()
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|