Skip to content

Commit d8003fc

Browse files
committed
Update bit masks to be more about sets than bits
Now bit masks functionality is designed around set operations (Union, Intersection, Difference, Symmetric Difference) instead of bit operations (And, Or, Not, Xor).
1 parent af755f4 commit d8003fc

File tree

4 files changed

+78
-102
lines changed

4 files changed

+78
-102
lines changed

Runtime/EnumBitMask32.cs

+25-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace EnumBitSet
77
{
88
[Serializable]
9-
public readonly struct EnumBitMask32<T> : IBitMask<EnumBitMask32<T>, T>
9+
public readonly struct EnumBitMask32<T> : IBitMask<EnumBitMask32<T>, T>, IEquatable<EnumBitMask32<T>>
1010
where T : struct, Enum
1111
{
1212
public int Mask => _data;
@@ -32,24 +32,40 @@ public EnumBitMask32(params T[] values) : this((IEnumerable<T>) values) {}
3232

3333
#region IBitMask<EnumBitMask32<T>, T>
3434

35-
public EnumBitMask32<T> BitAnd(EnumBitMask32<T> other)
35+
public EnumBitMask32<T> Union(T value)
3636
{
37-
return new EnumBitMask32<T>(_data & other._data);
37+
int mask = GetIntBitMask(value);
38+
return new EnumBitMask32<T>(_data | mask);
3839
}
3940

40-
public EnumBitMask32<T> BitOr(EnumBitMask32<T> other)
41+
public EnumBitMask32<T> Union(IEnumerable<T> other)
4142
{
42-
return new EnumBitMask32<T>(_data | other._data);
43+
int mask = GetIntBitMask(other);
44+
return new EnumBitMask32<T>(_data | mask);
4345
}
4446

45-
public EnumBitMask32<T> BitXor(EnumBitMask32<T> other)
47+
public EnumBitMask32<T> Intersection(IEnumerable<T> other)
4648
{
47-
return new EnumBitMask32<T>(_data ^ other._data);
49+
int mask = GetIntBitMask(other);
50+
return new EnumBitMask32<T>(_data & mask);
4851
}
4952

50-
public EnumBitMask32<T> BitNot()
53+
public EnumBitMask32<T> Difference(T value)
5154
{
52-
return new EnumBitMask32<T>(~_data);
55+
int mask = GetIntBitMask(value);
56+
return new EnumBitMask32<T>(_data & ~mask);
57+
}
58+
59+
public EnumBitMask32<T> Difference(IEnumerable<T> other)
60+
{
61+
int mask = GetIntBitMask(other);
62+
return new EnumBitMask32<T>(_data & ~mask);
63+
}
64+
65+
public EnumBitMask32<T> SymmetricDifference(IEnumerable<T> other)
66+
{
67+
int mask = GetIntBitMask(other);
68+
return new EnumBitMask32<T>(_data ^ mask);
5369
}
5470

5571
public EnumBitMask32<T> GetBitMask(T data)

Runtime/EnumBitMask64.cs

+25-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace EnumBitSet
77
{
88
[Serializable]
9-
public readonly struct EnumBitMask64<T> : IBitMask<EnumBitMask64<T>, T>
9+
public readonly struct EnumBitMask64<T> : IBitMask<EnumBitMask64<T>, T>, IEquatable<EnumBitMask64<T>>
1010
where T : struct, Enum
1111
{
1212
public long Mask => _data;
@@ -32,24 +32,40 @@ public EnumBitMask64(params T[] values) : this((IEnumerable<T>) values) {}
3232

3333
#region IBitMask<EnumBitMask64<T>, T>
3434

35-
public EnumBitMask64<T> BitAnd(EnumBitMask64<T> other)
35+
public EnumBitMask64<T> Union(T value)
3636
{
37-
return new EnumBitMask64<T>(_data & other._data);
37+
var mask = GetLongBitMask(value);
38+
return new EnumBitMask64<T>(_data | mask);
3839
}
3940

40-
public EnumBitMask64<T> BitOr(EnumBitMask64<T> other)
41+
public EnumBitMask64<T> Union(IEnumerable<T> other)
4142
{
42-
return new EnumBitMask64<T>(_data | other._data);
43+
var mask = GetLongBitMask(other);
44+
return new EnumBitMask64<T>(_data | mask);
45+
}
46+
47+
public EnumBitMask64<T> Intersection(IEnumerable<T> other)
48+
{
49+
var mask = GetLongBitMask(other);
50+
return new EnumBitMask64<T>(_data & mask);
4351
}
4452

45-
public EnumBitMask64<T> BitXor(EnumBitMask64<T> other)
53+
public EnumBitMask64<T> Difference(T value)
4654
{
47-
return new EnumBitMask64<T>(_data ^ other._data);
55+
var mask = GetLongBitMask(value);
56+
return new EnumBitMask64<T>(_data & ~mask);
4857
}
4958

50-
public EnumBitMask64<T> BitNot()
59+
public EnumBitMask64<T> Difference(IEnumerable<T> other)
5160
{
52-
return new EnumBitMask64<T>(~_data);
61+
var mask = GetLongBitMask(other);
62+
return new EnumBitMask64<T>(_data & ~mask);
63+
}
64+
65+
public EnumBitMask64<T> SymmetricDifference(IEnumerable<T> other)
66+
{
67+
var mask = GetLongBitMask(other);
68+
return new EnumBitMask64<T>(_data ^ mask);
5369
}
5470

5571
public EnumBitMask64<T> GetBitMask(T data)

Runtime/EnumBitSet.cs

+18-73
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,16 @@ public EnumBitSet() {}
1616

1717
public EnumBitSet(T value)
1818
{
19-
_data = GetBitMask(value);
19+
_data = _data.GetBitMask(value);
2020
}
2121

2222
public EnumBitSet(IEnumerable<T> values)
2323
{
24-
_data = GetBitMask(values);
24+
_data = _data.GetBitMask(values);
2525
}
2626

2727
public EnumBitSet(params T[] values) : this((IEnumerable<T>) values) {}
2828

29-
public bool this[T index]
30-
{
31-
get => this[GetBitMask(index)];
32-
set => this[GetBitMask(index)] = value;
33-
}
34-
35-
public bool this[IEnumerable<T> index]
36-
{
37-
get => this[GetBitMask(index)];
38-
set => this[GetBitMask(index)] = value;
39-
}
40-
41-
public bool this[params T[] indices]
42-
{
43-
get => this[(IEnumerable<T>) indices];
44-
set => this[(IEnumerable<T>) indices] = value;
45-
}
46-
4729
public bool Any()
4830
{
4931
return _data.HaveSetBits();
@@ -53,60 +35,52 @@ public bool Any()
5335

5436
public void ExceptWith(IEnumerable<T> other)
5537
{
56-
this[other] = false;
38+
_data = _data.Difference(other);
5739
}
5840

5941
public void IntersectWith(IEnumerable<T> other)
6042
{
61-
var mask = GetBitMask(other);
62-
_data = _data.BitAnd(mask);
43+
_data = _data.Intersection(other);
6344
}
6445

6546
public bool IsProperSubsetOf(IEnumerable<T> other)
6647
{
67-
var mask = GetBitMask(other);
68-
return _data.BitAnd(mask).Equals(_data) && mask.BitAnd(_data.BitNot()).HaveSetBits();
48+
return _data.IsProperSubsetOf(other);
6949
}
7050

7151
public bool IsProperSupersetOf(IEnumerable<T> other)
7252
{
73-
var mask = GetBitMask(other);
74-
return mask.BitAnd(_data).Equals(mask) && _data.BitAnd(mask.BitNot()).HaveSetBits();
53+
return _data.IsProperSupersetOf(other);
7554
}
7655

7756
public bool IsSubsetOf(IEnumerable<T> other)
7857
{
79-
var mask = GetBitMask(other);
80-
return _data.BitAnd(mask).Equals(_data);
58+
return _data.IsSubsetOf(other);
8159
}
8260

8361
public bool IsSupersetOf(IEnumerable<T> other)
8462
{
85-
var mask = GetBitMask(other);
86-
return mask.BitAnd(_data).Equals(mask);
63+
return _data.IsSupersetOf(other);
8764
}
8865

8966
public bool Overlaps(IEnumerable<T> other)
9067
{
91-
var mask = GetBitMask(other);
92-
return _data.BitAnd(mask).HaveSetBits();
68+
return _data.Overlaps(other);
9369
}
9470

9571
public bool SetEquals(IEnumerable<T> other)
9672
{
97-
var mask = GetBitMask(other);
98-
return _data.Equals(mask);
73+
return _data.SetEquals(other);
9974
}
10075

10176
public void SymmetricExceptWith(IEnumerable<T> other)
10277
{
103-
var mask = GetBitMask(other);
104-
_data = _data.BitXor(mask);
78+
_data = _data.SymmetricDifference(other);
10579
}
10680

10781
public void UnionWith(IEnumerable<T> other)
10882
{
109-
this[other] = true;
83+
_data = _data.Union(other);
11084
}
11185

11286
#endregion
@@ -115,16 +89,16 @@ public void UnionWith(IEnumerable<T> other)
11589

11690
void ICollection<T>.Add(T item)
11791
{
118-
this[item] = true;
92+
_data = _data.Union(item);
11993
}
12094

12195
public bool Add(T item)
12296
{
123-
if (this[item])
97+
if (_data.Contains(item))
12498
{
12599
return false;
126100
}
127-
this[item] = true;
101+
_data = _data.Union(item);
128102
return true;
129103
}
130104

@@ -135,7 +109,7 @@ public void Clear()
135109

136110
public bool Contains(T item)
137111
{
138-
return this[item];
112+
return _data.Contains(item);
139113
}
140114

141115
public void CopyTo(T[] array, int arrayIndex)
@@ -163,11 +137,11 @@ public void CopyTo(T[] array, int arrayIndex)
163137

164138
public bool Remove(T item)
165139
{
166-
if (!this[item])
140+
if (!_data.Contains(item))
167141
{
168142
return false;
169143
}
170-
this[item] = false;
144+
_data = _data.Difference(item);
171145
return true;
172146
}
173147

@@ -190,34 +164,5 @@ IEnumerator IEnumerable.GetEnumerator()
190164
}
191165

192166
#endregion
193-
194-
private bool this[TData mask]
195-
{
196-
get => mask.HaveSetBits() && _data.BitAnd(mask).Equals(mask);
197-
set => _data = value ? _data.BitOr(mask) : _data.BitAnd(mask.BitNot());
198-
}
199-
200-
private TData GetBitMask(T value)
201-
{
202-
return _data.GetBitMask(value);
203-
}
204-
205-
private TData GetBitMask(IEnumerable<T> other)
206-
{
207-
switch (other)
208-
{
209-
case TData data:
210-
return data;
211-
212-
case EnumBitSet<T, TData> bitset:
213-
return bitset._data;
214-
215-
case null:
216-
throw new ArgumentNullException(nameof(other), "Value cannot be null.");
217-
218-
default:
219-
return _data.GetBitMask(other);
220-
}
221-
}
222167
}
223168
}

Runtime/IBitMask.cs

+10-11
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
1-
using System;
21
using System.Collections.Generic;
32

43
namespace EnumBitSet
54
{
6-
public interface IBitMask<TData, TConvertible> : IReadOnlySet<TConvertible>, IEquatable<TData>
7-
where TData : struct
8-
where TConvertible : IConvertible
5+
public interface IBitMask<TData, T> : IReadOnlySet<T>
96
{
10-
TData BitAnd(TData other);
11-
TData BitOr(TData other);
12-
TData BitXor(TData other);
13-
TData BitNot();
7+
TData Union(T value);
8+
TData Union(IEnumerable<T> other);
9+
TData Intersection(IEnumerable<T> other);
10+
TData Difference(T value);
11+
TData Difference(IEnumerable<T> other);
12+
TData SymmetricDifference(IEnumerable<T> other);
1413

15-
TData GetBitMask(TConvertible data);
16-
TData GetBitMask(IEnumerable<TConvertible> data);
14+
TData GetBitMask(T data);
15+
TData GetBitMask(IEnumerable<T> data);
1716

1817
bool HaveSetBits();
1918
}
20-
19+
2120
#if !NET5_0_OR_GREATER
2221
public interface IReadOnlySet<T> : IReadOnlyCollection<T>
2322
{

0 commit comments

Comments
 (0)