github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/keyset/keyset_overlay.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package keyset 7 8 func newListOverlay(list KeyList) *listOverlay { 9 if list == nil { 10 panic("illegal value") 11 } 12 return &listOverlay{ 13 immutable: list, 14 includes: inclusiveMutable{inclusiveKeySet{emptyBasicKeySet}}, 15 excludes: exclusiveMutable{exclusiveKeySet{emptyBasicKeySet}}, 16 } 17 } 18 19 func newMutableOverlay(list KeyList) mutableKeySet { 20 return &inclusiveMutableOverlay{inclusiveKeySet{newListOverlay(list)}} 21 } 22 23 func emptyInclusiveMutable() *inclusiveMutable { 24 return &inclusiveMutable{inclusiveKeySet{emptyBasicKeySet}} 25 } 26 27 var _ internalKeySet = &listOverlay{} 28 29 type listOverlay struct { 30 immutable KeyList 31 includes inclusiveMutable 32 excludes exclusiveMutable 33 } 34 35 func (v *listOverlay) Count() int { 36 return v.immutable.Count() - v.excludes.RawKeyCount() + v.includes.RawKeyCount() 37 } 38 39 func (v *listOverlay) Contains(k Key) bool { 40 return v.excludes.Contains(k) && (v.immutable.Contains(k) || v.includes.Contains(k)) 41 } 42 43 func (v *listOverlay) EnumKeys(fn func(k Key) bool) bool { 44 if v.includes.keys.EnumKeys(fn) { 45 return true 46 } 47 return v.immutable.EnumKeys(func(k Key) bool { 48 if !v.excludes.Contains(k) { 49 return false 50 } 51 return fn(k) 52 }) 53 } 54 55 func (v *listOverlay) enumRawKeys(exclusive bool, fn func(k Key, exclusive bool) bool) bool { 56 if v.includes.EnumRawKeys(fn) { 57 return true 58 } 59 return v.immutable.EnumKeys(func(k Key) bool { 60 if !v.excludes.Contains(k) { 61 return false 62 } 63 return fn(k, false) 64 }) 65 } 66 67 func (v *listOverlay) copy(n int) basicKeySet { 68 return listSet{v}.copy(n) 69 } 70 71 func (v *listOverlay) isEmpty() bool { 72 switch n := v.immutable.Count(); { 73 case v.includes.RawKeyCount() > 0: 74 return false 75 case n == 0: 76 return true 77 default: 78 return n == v.excludes.RawKeyCount() 79 } 80 } 81 82 func (v *listOverlay) _remove(k Key) { 83 v.includes.remove(k) 84 if v.immutable.Contains(k) { 85 v.excludes.remove(k) 86 } 87 } 88 89 func (v *listOverlay) _add(k Key) { 90 v.excludes.add(k) 91 if !v.immutable.Contains(k) { 92 v.includes.add(k) 93 } 94 } 95 96 var _ mutableKeySet = &inclusiveMutableOverlay{} 97 98 type inclusiveMutableOverlay struct { 99 inclusiveKeySet 100 } 101 102 func (v *inclusiveMutableOverlay) copy(n int) basicKeySet { 103 return v.keys.copy(n) 104 } 105 106 func (v *inclusiveMutableOverlay) retainAll(ks KeySet) mutableKeySet { 107 keys := v.keys.(*listOverlay) 108 109 if keys.isEmpty() { 110 return nil 111 } 112 113 switch kn := ks.RawKeyCount(); { 114 case kn == 0: 115 if !ks.IsOpenSet() { 116 return emptyInclusiveMutable() 117 } 118 return nil 119 case ks.IsOpenSet() && kn < keys.Count(): 120 ks.EnumRawKeys(func(k Key, exclusive bool) bool { 121 keys._remove(k) 122 return keys.isEmpty() 123 }) 124 default: 125 // TODO PLAT-20 efficiency can be improved 126 keys.EnumKeys(func(k Key) bool { 127 if !ks.Contains(k) { 128 keys._remove(k) 129 } 130 return false 131 }) 132 } 133 134 if keys.isEmpty() { 135 return emptyInclusiveMutable() 136 } 137 return nil 138 } 139 140 func (v *inclusiveMutableOverlay) removeAll(ks KeySet) mutableKeySet { 141 keys := v.keys.(*listOverlay) 142 prevIncludes := keys.includes.RawKeyCount() 143 144 switch { 145 case keys.isEmpty(): 146 return nil 147 case !ks.IsOpenSet(): 148 keys.includes.removeAll(ks) 149 case ks.RawKeyCount() < keys.Count(): 150 var newKeys basicKeySet 151 ks.EnumRawKeys(func(k Key, _ bool) bool { 152 if keys.Contains(k) { 153 if newKeys == nil { 154 // there will be no more than ks.RawKeyCount() ... 155 newKeys = newBasicKeySet(0) 156 } 157 newKeys.add(k) 158 } 159 return false 160 }) 161 return &inclusiveMutable{inclusiveKeySet{newKeys}} 162 default: 163 keys.includes.retainAll(ks.Inverse()) 164 } 165 166 if prevIncludes == keys.includes.RawKeyCount()+ks.RawKeyCount() { 167 return nil 168 } 169 170 keys.immutable.EnumKeys(func(k Key) bool { 171 if keys.excludes.Contains(k) && ks.Contains(k) { 172 keys.excludes.remove(k) 173 } 174 return keys.immutable.Count() == keys.excludes.RawKeyCount() 175 }) 176 177 if keys.isEmpty() { 178 return emptyInclusiveMutable() 179 } 180 return nil 181 } 182 183 func (v *inclusiveMutableOverlay) addAll(ks KeySet) mutableKeySet { 184 keys := v.keys.(*listOverlay) 185 186 if ks.IsOpenSet() { 187 // NB! it changes a type of the set to exclusive 188 var newKeys basicKeySet 189 ks.EnumRawKeys(func(k Key, _ bool) bool { 190 if !keys.Contains(k) { 191 if newKeys == nil { 192 newKeys = newBasicKeySet(ks.RawKeyCount()) 193 } 194 newKeys.add(k) 195 } 196 return false 197 }) 198 return &exclusiveMutable{exclusiveKeySet{newKeys}} 199 } 200 201 kn := ks.RawKeyCount() 202 if kn == 0 { 203 return nil 204 } 205 206 ks.EnumRawKeys(func(k Key, _ bool) bool { 207 keys._add(k) 208 return false 209 }) 210 return nil 211 } 212 213 func (v *inclusiveMutableOverlay) removeKeys(ks []Key) { 214 p := v.keys.(*listOverlay) 215 p.includes.removeKeys(ks) 216 for _, k := range ks { 217 if p.immutable.Contains(k) { 218 p.excludes.remove(k) 219 } 220 } 221 } 222 223 func (v *inclusiveMutableOverlay) addKeys(ks []Key) { 224 p := v.keys.(*listOverlay) 225 p.excludes.addKeys(ks) 226 for _, k := range ks { 227 if !p.immutable.Contains(k) { 228 p.includes.add(k) 229 } 230 } 231 } 232 233 func (v *inclusiveMutableOverlay) remove(k Key) { 234 p := v.keys.(*listOverlay) 235 p._remove(k) 236 } 237 238 func (v *inclusiveMutableOverlay) add(k Key) { 239 p := v.keys.(*listOverlay) 240 p._add(k) 241 }