-
Notifications
You must be signed in to change notification settings - Fork 2
/
keyset.go
131 lines (116 loc) · 3.29 KB
/
keyset.go
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
131
package keyset
import "github.com/insolar/vanilla/longbits"
type Key = longbits.ByteString
// A basic set of keys, that can be wrapped by an extra keyset logic.
type KeyList interface {
// returns true when the given key is within the set
Contains(Key) bool
// lists keys
EnumKeys(func(k Key) bool) bool
// number of unique keys
Count() int
}
// An advanced set of keys, that also represent an open set (tracks exclusions, not inclusions)
//
// NB! An immutable inclusive/closed set MUST be able to cast to KeyList & InclusiveKeySet.
// An open or a mutable KeySet MUST NOT be able to cast to KeyList & InclusiveKeySet.
// This behavior is supported by this package.
//
type KeySet interface {
// returns true when this set is empty
IsNothing() bool
// returns true when this set matches everything
IsEverything() bool
// returns true when the set is open / unbound and only Contains exclusions
IsOpenSet() bool
// returns true when the given key is within the set
Contains(Key) bool
// returns true when any key of the given set is within this set
ContainsAny(KeySet) bool
// returns true when this set Contains all keys from the given one
SupersetOf(KeySet) bool
// returns true when all keys of this set are contained in the given one
SubsetOf(KeySet) bool
// returns true when both sets have same set of keys
Equal(KeySet) bool
// a faster equivalent of Equal(ks.Inverse())
EqualInverse(KeySet) bool
// returns a set that has all keys but this set
Inverse() KeySet
// returns a set of keys present in at least one sets
Union(KeySet) KeySet
// returns a set of keys present in both sets
Intersect(KeySet) KeySet
// returns a set of keys present in this set and not present in the given set
Subtract(KeySet) KeySet
// WARNING! Do not use
// lists keys (when IsOpenSet() == true, as then it lists _excluded_ keys)
EnumRawKeys(func(k Key, exclusive bool) bool) bool
// WARNING! Do not use. This must NOT be treated as a size of a set.
// number of keys (when IsOpenSet() == true, as then it gives a number of _excluded_ keys)
RawKeyCount() int
}
type InclusiveKeySet interface {
KeySet
// lists keys
EnumKeys(func(k Key) bool) bool
// number of unique keys
Count() int
}
func New(keys []Key) KeySet {
n := len(keys)
switch n {
case 0:
return Nothing()
case 1:
return SoloKeySet(keys[0])
}
ks := make(basicKeySet, n)
for _, k := range keys {
ks.add(k)
}
return inclusiveKeySet{ks}
}
func Wrap(keys KeyList) KeySet {
if keys == nil {
panic("illegal state")
}
return inclusiveKeySet{listSet{keys}}
}
func CopyList(keys KeyList) KeySet {
n := keys.Count()
if n == 0 {
return Nothing()
}
return inclusiveKeySet{listSet{keys}.copy(0)}
}
func CopySet(keys KeySet) KeySet {
if iks, ok := keys.(internalKeySet); ok {
return newKeySet(keys.IsOpenSet(), iks.copy(0))
}
switch n := keys.RawKeyCount(); {
case n > 0:
ks := make(basicKeySet, n)
keys.EnumRawKeys(func(k Key, _ bool) bool {
ks.add(k)
return false
})
return newKeySet(keys.IsOpenSet(), ks)
case n != 0:
panic("illegal state")
case keys.IsOpenSet():
return Everything()
default:
return Nothing()
}
}
func newKeySet(exclusive bool, ks internalKeySet) KeySet {
switch {
case ks == nil:
panic("illegal value")
case exclusive:
return exclusiveKeySet{ks}
default:
return inclusiveKeySet{ks}
}
}