com.wallstop-studios.unity-helpers 2.0.0-rc46 → 2.0.0-rc48

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.
@@ -125,7 +125,11 @@
125
125
  {
126
126
  if (dictionary is ConcurrentDictionary<K, V> concurrentDictionary)
127
127
  {
128
- return concurrentDictionary.AddOrUpdate(key, creator, (_, existing) => existing);
128
+ return concurrentDictionary.AddOrUpdate(
129
+ key,
130
+ creator,
131
+ (_, existingValue) => existingValue
132
+ );
129
133
  }
130
134
 
131
135
  if (dictionary.TryGetValue(key, out V existing))
@@ -206,6 +210,14 @@
206
210
  return new Dictionary<K, V>(dictionary);
207
211
  }
208
212
 
213
+ public static Dictionary<K, V> ToDictionary<K, V>(
214
+ this IReadOnlyDictionary<K, V> dictionary,
215
+ IEqualityComparer<K> comparer
216
+ )
217
+ {
218
+ return new Dictionary<K, V>(dictionary, comparer);
219
+ }
220
+
209
221
  public static Dictionary<K, V> ToDictionary<K, V>(
210
222
  this IEnumerable<KeyValuePair<K, V>> prettyMuchADictionary
211
223
  )
@@ -213,6 +225,14 @@
213
225
  return prettyMuchADictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
214
226
  }
215
227
 
228
+ public static Dictionary<K, V> ToDictionary<K, V>(
229
+ this IEnumerable<KeyValuePair<K, V>> prettyMuchADictionary,
230
+ IEqualityComparer<K> comparer
231
+ )
232
+ {
233
+ return prettyMuchADictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value, comparer);
234
+ }
235
+
216
236
  public static Dictionary<K, V> ToDictionary<K, V>(
217
237
  this IEnumerable<(K, V)> prettyMuchADictionary
218
238
  )
@@ -220,6 +240,14 @@
220
240
  return prettyMuchADictionary.ToDictionary(kvp => kvp.Item1, kvp => kvp.Item2);
221
241
  }
222
242
 
243
+ public static Dictionary<K, V> ToDictionary<K, V>(
244
+ this IEnumerable<(K, V)> prettyMuchADictionary,
245
+ IEqualityComparer<K> comparer
246
+ )
247
+ {
248
+ return prettyMuchADictionary.ToDictionary(kvp => kvp.Item1, kvp => kvp.Item2, comparer);
249
+ }
250
+
223
251
  public static bool ContentEquals<K, V>(
224
252
  this IReadOnlyDictionary<K, V> dictionary,
225
253
  IReadOnlyDictionary<K, V> other
@@ -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,3 @@
1
+ fileFormatVersion: 2
2
+ guid: cb447d880798449cb844f63991aac81b
3
+ timeCreated: 1742771382
@@ -52,10 +52,7 @@
52
52
  return;
53
53
  }
54
54
 
55
- while (Interlocked.CompareExchange(ref _active, 0, _active) != 0)
56
- {
57
- // Spin
58
- }
55
+ Interlocked.Exchange(ref _active, 0);
59
56
 
60
57
  if (disposing)
61
58
  {
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 08e6640512474d02bc94651af90a6ffd
3
+ timeCreated: 1742771579
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.wallstop-studios.unity-helpers",
3
- "version": "2.0.0-rc46",
3
+ "version": "2.0.0-rc48",
4
4
  "displayName": "Unity Helpers",
5
5
  "description": "Various Unity Helper Library",
6
6
  "dependencies": {},