Replace the setmatrix package's use of golang-set with a small local
map-backed set implementation. The package already serializes access with
its own mutex, so the external dependency was not buying us much and made
this small utility harder to keep self-contained.
Removing it trims the dependency surface and avoids carrying an otherwise
single-purpose module for a narrow internal use case.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
| ... | ... |
@@ -1,17 +1,57 @@ |
| 1 | 1 |
package setmatrix |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "fmt" |
|
| 4 | 5 |
"sync" |
| 5 |
- |
|
| 6 |
- mapset "github.com/deckarep/golang-set/v2" |
|
| 7 | 6 |
) |
| 8 | 7 |
|
| 8 |
+type set[V comparable] map[V]struct{}
|
|
| 9 |
+ |
|
| 10 |
+func newSet[V comparable](value V) set[V] {
|
|
| 11 |
+ s := make(set[V], 1) |
|
| 12 |
+ s[value] = struct{}{}
|
|
| 13 |
+ return s |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 16 |
+func (s set[V]) Add(value V) bool {
|
|
| 17 |
+ if _, ok := s[value]; ok {
|
|
| 18 |
+ return false |
|
| 19 |
+ } |
|
| 20 |
+ s[value] = struct{}{}
|
|
| 21 |
+ return true |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func (s set[V]) Contains(value V) bool {
|
|
| 25 |
+ _, ok := s[value] |
|
| 26 |
+ return ok |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+func (s set[V]) Remove(value V) {
|
|
| 30 |
+ delete(s, value) |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+func (s set[V]) Cardinality() int {
|
|
| 34 |
+ return len(s) |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func (s set[V]) ToSlice() []V {
|
|
| 38 |
+ values := make([]V, 0, len(s)) |
|
| 39 |
+ for value := range s {
|
|
| 40 |
+ values = append(values, value) |
|
| 41 |
+ } |
|
| 42 |
+ return values |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+func (s set[V]) String() string {
|
|
| 46 |
+ return fmt.Sprint(s.ToSlice()) |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 9 | 49 |
// SetMatrix is a map of Sets. |
| 10 | 50 |
// The zero value is an empty set matrix ready to use. |
| 11 | 51 |
// |
| 12 | 52 |
// SetMatrix values are safe for concurrent use. |
| 13 | 53 |
type SetMatrix[K, V comparable] struct {
|
| 14 |
- matrix map[K]mapset.Set[V] |
|
| 54 |
+ matrix map[K]set[V] |
|
| 15 | 55 |
|
| 16 | 56 |
mu sync.Mutex |
| 17 | 57 |
} |
| ... | ... |
@@ -43,16 +83,16 @@ func (s *SetMatrix[K, V]) Contains(key K, value V) (containsElement, setExists b |
| 43 | 43 |
func (s *SetMatrix[K, V]) Insert(key K, value V) (inserted bool, cardinality int) {
|
| 44 | 44 |
s.mu.Lock() |
| 45 | 45 |
defer s.mu.Unlock() |
| 46 |
- set, ok := s.matrix[key] |
|
| 46 |
+ values, ok := s.matrix[key] |
|
| 47 | 47 |
if !ok {
|
| 48 | 48 |
if s.matrix == nil {
|
| 49 |
- s.matrix = make(map[K]mapset.Set[V]) |
|
| 49 |
+ s.matrix = make(map[K]set[V]) |
|
| 50 | 50 |
} |
| 51 |
- s.matrix[key] = mapset.NewThreadUnsafeSet(value) |
|
| 51 |
+ s.matrix[key] = newSet(value) |
|
| 52 | 52 |
return true, 1 |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 |
- return set.Add(value), set.Cardinality() |
|
| 55 |
+ return values.Add(value), values.Cardinality() |
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 | 58 |
// Remove removes the value in the set for a specific key. |
| ... | ... |
@@ -32,7 +32,6 @@ require ( |
| 32 | 32 |
github.com/coreos/go-systemd/v22 v22.7.0 |
| 33 | 33 |
github.com/cpuguy83/tar2go v0.3.1 |
| 34 | 34 |
github.com/creack/pty v1.1.24 |
| 35 |
- github.com/deckarep/golang-set/v2 v2.8.0 |
|
| 36 | 35 |
github.com/distribution/reference v0.6.0 |
| 37 | 36 |
github.com/docker/distribution v2.8.3+incompatible |
| 38 | 37 |
github.com/docker/go-connections v0.7.0 |
| ... | ... |
@@ -216,8 +216,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs |
| 216 | 216 |
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
| 217 | 217 |
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= |
| 218 | 218 |
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
| 219 |
-github.com/deckarep/golang-set/v2 v2.8.0 h1:swm0rlPCmdWn9mESxKOjWk8hXSqoxOp+ZlfuyaAdFlQ= |
|
| 220 |
-github.com/deckarep/golang-set/v2 v2.8.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= |
|
| 221 | 219 |
github.com/digitorus/pkcs7 v0.0.0-20230713084857-e76b763bdc49/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= |
| 222 | 220 |
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 h1:ge14PCmCvPjpMQMIAH7uKg0lrtNSOdpYsRXlwk3QbaE= |
| 223 | 221 |
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= |
| 224 | 222 |
deleted file mode 100644 |
| ... | ... |
@@ -1,23 +0,0 @@ |
| 1 |
-# Compiled Object files, Static and Dynamic libs (Shared Objects) |
|
| 2 |
-*.o |
|
| 3 |
-*.a |
|
| 4 |
-*.so |
|
| 5 |
- |
|
| 6 |
-# Folders |
|
| 7 |
-_obj |
|
| 8 |
-_test |
|
| 9 |
- |
|
| 10 |
-# Architecture specific extensions/prefixes |
|
| 11 |
-*.[568vq] |
|
| 12 |
-[568vq].out |
|
| 13 |
- |
|
| 14 |
-*.cgo1.go |
|
| 15 |
-*.cgo2.c |
|
| 16 |
-_cgo_defun.c |
|
| 17 |
-_cgo_gotypes.go |
|
| 18 |
-_cgo_export.* |
|
| 19 |
- |
|
| 20 |
-_testmain.go |
|
| 21 |
- |
|
| 22 |
-*.exe |
|
| 23 |
-.idea |
|
| 24 | 1 |
\ No newline at end of file |
| 25 | 2 |
deleted file mode 100644 |
| ... | ... |
@@ -1,22 +0,0 @@ |
| 1 |
-Open Source Initiative OSI - The MIT License (MIT):Licensing |
|
| 2 |
- |
|
| 3 |
-The MIT License (MIT) |
|
| 4 |
-Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) |
|
| 5 |
- |
|
| 6 |
-Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
| 7 |
-this software and associated documentation files (the "Software"), to deal in |
|
| 8 |
-the Software without restriction, including without limitation the rights to |
|
| 9 |
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|
| 10 |
-of the Software, and to permit persons to whom the Software is furnished to do |
|
| 11 |
-so, subject to the following conditions: |
|
| 12 |
- |
|
| 13 |
-The above copyright notice and this permission notice shall be included in all |
|
| 14 |
-copies or substantial portions of the Software. |
|
| 15 |
- |
|
| 16 |
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 17 |
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
| 18 |
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
| 19 |
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
| 20 |
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
| 21 |
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
| 22 |
-SOFTWARE. |
|
| 23 | 1 |
\ No newline at end of file |
| 24 | 2 |
deleted file mode 100644 |
| ... | ... |
@@ -1,195 +0,0 @@ |
| 1 |
- |
|
| 2 |
-[](https://goreportcard.com/report/github.com/deckarep/golang-set/v2) |
|
| 3 |
-[](http://godoc.org/github.com/deckarep/golang-set/v2) |
|
| 4 |
- |
|
| 5 |
-# golang-set |
|
| 6 |
- |
|
| 7 |
-The missing `generic` set collection for the Go language. Until Go has sets built-in...use this. |
|
| 8 |
- |
|
| 9 |
-## Psst |
|
| 10 |
-* Hi there, 👋! Do you use or have interest in the [Zig programming language](https://ziglang.org/) created by Andrew Kelley? If so, the golang-set project has a new sibling project: [ziglang-set](https://github.com/deckarep/ziglang-set)! Come check it out! |
|
| 11 |
- |
|
| 12 |
-## Update 3/14/2025 |
|
| 13 |
-* Packaged version: `2.8.0` introduces support for true iterators for Go 1.23+. Please see [issue #141](https://github.com/deckarep/golang-set/issues/141) |
|
| 14 |
-for further details on the implications of how iterations work between older Go versions vs newer Go versions. Additionally, this |
|
| 15 |
-release has a minor unit-test spelling fix. |
|
| 16 |
- |
|
| 17 |
-## Update 12/3/2024 |
|
| 18 |
-* Packaged version: `2.7.0` fixes a long-standing bug with *JSON Unmarshaling*. A large refactor in the interest of performance |
|
| 19 |
-introduced this bug and there was no way around it but to revert the code back to how it was previously. The performance |
|
| 20 |
-difference was likely negligible to begin with. JSON Marshaling and Unmarshaling is now properly supported again without |
|
| 21 |
-needing to do workarounds. |
|
| 22 |
- |
|
| 23 |
-## Update 3/5/2023 |
|
| 24 |
-* Packaged version: `2.2.0` release includes a refactor to minimize pointer indirection, better method documentation standards and a few constructor convenience methods to increase ergonomics when appending items `Append` or creating a new set from an exist `Map`. |
|
| 25 |
-* supports `new generic` syntax |
|
| 26 |
-* Go `1.18.0` or higher |
|
| 27 |
-* Workflow tested on Go `1.20` |
|
| 28 |
- |
|
| 29 |
- |
|
| 30 |
- |
|
| 31 |
-Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set collection from Python. |
|
| 32 |
-You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository and carry-on and to the rest that find this useful please contribute in helping me make it better by contributing with suggestions or PRs. |
|
| 33 |
- |
|
| 34 |
-## Install |
|
| 35 |
- |
|
| 36 |
-Use `go get` to install this package. |
|
| 37 |
- |
|
| 38 |
-```shell |
|
| 39 |
-go get github.com/deckarep/golang-set/v2 |
|
| 40 |
-``` |
|
| 41 |
- |
|
| 42 |
-## Features |
|
| 43 |
- |
|
| 44 |
-* *NEW* [Generics](https://go.dev/doc/tutorial/generics) based implementation (requires [Go 1.18](https://go.dev/blog/go1.18beta1) or higher) |
|
| 45 |
-* One common *interface* to both implementations |
|
| 46 |
- * a **non threadsafe** implementation favoring *performance* |
|
| 47 |
- * a **threadsafe** implementation favoring *concurrent* use |
|
| 48 |
-* Feature complete set implementation modeled after [Python's set implementation](https://docs.python.org/3/library/stdtypes.html#set). |
|
| 49 |
-* Exhaustive unit-test and benchmark suite |
|
| 50 |
- |
|
| 51 |
-## Trusted by |
|
| 52 |
- |
|
| 53 |
-This package is trusted by many companies and thousands of open-source packages. Here are just a few sample users of this package. |
|
| 54 |
- |
|
| 55 |
-* Notable projects/companies using this package |
|
| 56 |
- * Ethereum |
|
| 57 |
- * Docker |
|
| 58 |
- * 1Password |
|
| 59 |
- * Hashicorp |
|
| 60 |
- |
|
| 61 |
-## Star History |
|
| 62 |
- |
|
| 63 |
-[](https://star-history.com/#deckarep/golang-set&Date) |
|
| 64 |
- |
|
| 65 |
- |
|
| 66 |
-## Usage |
|
| 67 |
- |
|
| 68 |
-The code below demonstrates how a Set collection can better manage data and actually minimize boilerplate and needless loops in code. This package now fully supports *generic* syntax so you are now able to instantiate a collection for any [comparable](https://flaviocopes.com/golang-comparing-values/) type object. |
|
| 69 |
- |
|
| 70 |
-What is considered comparable in Go? |
|
| 71 |
-* `Booleans`, `integers`, `strings`, `floats` or basically primitive types. |
|
| 72 |
-* `Pointers` |
|
| 73 |
-* `Arrays` |
|
| 74 |
-* `Structs` if *all of their fields* are also comparable independently |
|
| 75 |
- |
|
| 76 |
-Using this library is as simple as creating either a threadsafe or non-threadsafe set and providing a `comparable` type for instantiation of the collection. |
|
| 77 |
- |
|
| 78 |
-```go |
|
| 79 |
-// Syntax example, doesn't compile. |
|
| 80 |
-mySet := mapset.NewSet[T]() // where T is some concrete comparable type. |
|
| 81 |
- |
|
| 82 |
-// Therefore this code creates an int set |
|
| 83 |
-mySet := mapset.NewSet[int]() |
|
| 84 |
- |
|
| 85 |
-// Or perhaps you want a string set |
|
| 86 |
-mySet := mapset.NewSet[string]() |
|
| 87 |
- |
|
| 88 |
-type myStruct struct {
|
|
| 89 |
- name string |
|
| 90 |
- age uint8 |
|
| 91 |
-} |
|
| 92 |
- |
|
| 93 |
-// Alternatively a set of structs |
|
| 94 |
-mySet := mapset.NewSet[myStruct]() |
|
| 95 |
- |
|
| 96 |
-// Lastly a set that can hold anything using the any or empty interface keyword: interface{}. This is effectively removes type safety.
|
|
| 97 |
-mySet := mapset.NewSet[any]() |
|
| 98 |
-``` |
|
| 99 |
- |
|
| 100 |
-## Comprehensive Example |
|
| 101 |
- |
|
| 102 |
-```go |
|
| 103 |
-package main |
|
| 104 |
- |
|
| 105 |
-import ( |
|
| 106 |
- "fmt" |
|
| 107 |
- mapset "github.com/deckarep/golang-set/v2" |
|
| 108 |
-) |
|
| 109 |
- |
|
| 110 |
-func main() {
|
|
| 111 |
- // Create a string-based set of required classes. |
|
| 112 |
- required := mapset.NewSet[string]() |
|
| 113 |
- required.Add("cooking")
|
|
| 114 |
- required.Add("english")
|
|
| 115 |
- required.Add("math")
|
|
| 116 |
- required.Add("biology")
|
|
| 117 |
- |
|
| 118 |
- // Create a string-based set of science classes. |
|
| 119 |
- sciences := mapset.NewSet[string]() |
|
| 120 |
- sciences.Add("biology")
|
|
| 121 |
- sciences.Add("chemistry")
|
|
| 122 |
- |
|
| 123 |
- // Create a string-based set of electives. |
|
| 124 |
- electives := mapset.NewSet[string]() |
|
| 125 |
- electives.Add("welding")
|
|
| 126 |
- electives.Add("music")
|
|
| 127 |
- electives.Add("automotive")
|
|
| 128 |
- |
|
| 129 |
- // Create a string-based set of bonus programming classes. |
|
| 130 |
- bonus := mapset.NewSet[string]() |
|
| 131 |
- bonus.Add("beginner go")
|
|
| 132 |
- bonus.Add("python for dummies")
|
|
| 133 |
-} |
|
| 134 |
-``` |
|
| 135 |
- |
|
| 136 |
-Create a set of all unique classes. |
|
| 137 |
-Sets will *automatically* deduplicate the same data. |
|
| 138 |
- |
|
| 139 |
-```go |
|
| 140 |
- all := required |
|
| 141 |
- .Union(sciences) |
|
| 142 |
- .Union(electives) |
|
| 143 |
- .Union(bonus) |
|
| 144 |
- |
|
| 145 |
- fmt.Println(all) |
|
| 146 |
-``` |
|
| 147 |
- |
|
| 148 |
-Output: |
|
| 149 |
-```sh |
|
| 150 |
-Set{cooking, english, math, chemistry, welding, biology, music, automotive, beginner go, python for dummies}
|
|
| 151 |
-``` |
|
| 152 |
- |
|
| 153 |
-Is cooking considered a science class? |
|
| 154 |
-```go |
|
| 155 |
-result := sciences.Contains("cooking")
|
|
| 156 |
-fmt.Println(result) |
|
| 157 |
-``` |
|
| 158 |
- |
|
| 159 |
-Output: |
|
| 160 |
-```false |
|
| 161 |
-false |
|
| 162 |
-``` |
|
| 163 |
- |
|
| 164 |
-Show me all classes that are not science classes, since I don't enjoy science. |
|
| 165 |
-```go |
|
| 166 |
-notScience := all.Difference(sciences) |
|
| 167 |
-fmt.Println(notScience) |
|
| 168 |
-``` |
|
| 169 |
- |
|
| 170 |
-```sh |
|
| 171 |
-Set{ music, automotive, beginner go, python for dummies, cooking, english, math, welding }
|
|
| 172 |
-``` |
|
| 173 |
- |
|
| 174 |
-Which science classes are also required classes? |
|
| 175 |
-```go |
|
| 176 |
-reqScience := sciences.Intersect(required) |
|
| 177 |
-``` |
|
| 178 |
- |
|
| 179 |
-Output: |
|
| 180 |
-```sh |
|
| 181 |
-Set{biology}
|
|
| 182 |
-``` |
|
| 183 |
- |
|
| 184 |
-How many bonus classes do you offer? |
|
| 185 |
-```go |
|
| 186 |
-fmt.Println(bonus.Cardinality()) |
|
| 187 |
-``` |
|
| 188 |
-Output: |
|
| 189 |
-```sh |
|
| 190 |
-2 |
|
| 191 |
-``` |
|
| 192 |
- |
|
| 193 |
-Thanks for visiting! |
|
| 194 |
- |
|
| 195 |
--deckarep |
| 196 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,58 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
-Open Source Initiative OSI - The MIT License (MIT):Licensing |
|
| 3 |
- |
|
| 4 |
-The MIT License (MIT) |
|
| 5 |
-Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) |
|
| 6 |
- |
|
| 7 |
-Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
| 8 |
-this software and associated documentation files (the "Software"), to deal in |
|
| 9 |
-the Software without restriction, including without limitation the rights to |
|
| 10 |
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|
| 11 |
-of the Software, and to permit persons to whom the Software is furnished to do |
|
| 12 |
-so, subject to the following conditions: |
|
| 13 |
- |
|
| 14 |
-The above copyright notice and this permission notice shall be included in all |
|
| 15 |
-copies or substantial portions of the Software. |
|
| 16 |
- |
|
| 17 |
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 18 |
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
| 19 |
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
| 20 |
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
| 21 |
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
| 22 |
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
| 23 |
-SOFTWARE. |
|
| 24 |
-*/ |
|
| 25 |
- |
|
| 26 |
-package mapset |
|
| 27 |
- |
|
| 28 |
-// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's |
|
| 29 |
-// elements. |
|
| 30 |
-type Iterator[T comparable] struct {
|
|
| 31 |
- C <-chan T |
|
| 32 |
- stop chan struct{}
|
|
| 33 |
-} |
|
| 34 |
- |
|
| 35 |
-// Stop stops the Iterator, no further elements will be received on C, C will be closed. |
|
| 36 |
-func (i *Iterator[T]) Stop() {
|
|
| 37 |
- // Allows for Stop() to be called multiple times |
|
| 38 |
- // (close() panics when called on already closed channel) |
|
| 39 |
- defer func() {
|
|
| 40 |
- recover() |
|
| 41 |
- }() |
|
| 42 |
- |
|
| 43 |
- close(i.stop) |
|
| 44 |
- |
|
| 45 |
- // Exhaust any remaining elements. |
|
| 46 |
- for range i.C {
|
|
| 47 |
- } |
|
| 48 |
-} |
|
| 49 |
- |
|
| 50 |
-// newIterator returns a new Iterator instance together with its item and stop channels. |
|
| 51 |
-func newIterator[T comparable]() (*Iterator[T], chan<- T, <-chan struct{}) {
|
|
| 52 |
- itemChan := make(chan T) |
|
| 53 |
- stopChan := make(chan struct{})
|
|
| 54 |
- return &Iterator[T]{
|
|
| 55 |
- C: itemChan, |
|
| 56 |
- stop: stopChan, |
|
| 57 |
- }, itemChan, stopChan |
|
| 58 |
-} |
| 61 | 3 |
deleted file mode 100644 |
| ... | ... |
@@ -1,269 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
-Open Source Initiative OSI - The MIT License (MIT):Licensing |
|
| 3 |
- |
|
| 4 |
-The MIT License (MIT) |
|
| 5 |
-Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) |
|
| 6 |
- |
|
| 7 |
-Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
| 8 |
-this software and associated documentation files (the "Software"), to deal in |
|
| 9 |
-the Software without restriction, including without limitation the rights to |
|
| 10 |
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|
| 11 |
-of the Software, and to permit persons to whom the Software is furnished to do |
|
| 12 |
-so, subject to the following conditions: |
|
| 13 |
- |
|
| 14 |
-The above copyright notice and this permission notice shall be included in all |
|
| 15 |
-copies or substantial portions of the Software. |
|
| 16 |
- |
|
| 17 |
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 18 |
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
| 19 |
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
| 20 |
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
| 21 |
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
| 22 |
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
| 23 |
-SOFTWARE. |
|
| 24 |
-*/ |
|
| 25 |
- |
|
| 26 |
-// Package mapset implements a simple and set collection. |
|
| 27 |
-// Items stored within it are unordered and unique. It supports |
|
| 28 |
-// typical set operations: membership testing, intersection, union, |
|
| 29 |
-// difference, symmetric difference and cloning. |
|
| 30 |
-// |
|
| 31 |
-// Package mapset provides two implementations of the Set |
|
| 32 |
-// interface. The default implementation is safe for concurrent |
|
| 33 |
-// access, but a non-thread-safe implementation is also provided for |
|
| 34 |
-// programs that can benefit from the slight speed improvement and |
|
| 35 |
-// that can enforce mutual exclusion through other means. |
|
| 36 |
-package mapset |
|
| 37 |
- |
|
| 38 |
-// Set is the primary interface provided by the mapset package. It |
|
| 39 |
-// represents an unordered set of data and a large number of |
|
| 40 |
-// operations that can be applied to that set. |
|
| 41 |
-type Set[T comparable] interface {
|
|
| 42 |
- // Add adds an element to the set. Returns whether |
|
| 43 |
- // the item was added. |
|
| 44 |
- Add(val T) bool |
|
| 45 |
- |
|
| 46 |
- // Append multiple elements to the set. Returns |
|
| 47 |
- // the number of elements added. |
|
| 48 |
- Append(val ...T) int |
|
| 49 |
- |
|
| 50 |
- // Cardinality returns the number of elements in the set. |
|
| 51 |
- Cardinality() int |
|
| 52 |
- |
|
| 53 |
- // Clear removes all elements from the set, leaving |
|
| 54 |
- // the empty set. |
|
| 55 |
- Clear() |
|
| 56 |
- |
|
| 57 |
- // Clone returns a clone of the set using the same |
|
| 58 |
- // implementation, duplicating all keys. |
|
| 59 |
- Clone() Set[T] |
|
| 60 |
- |
|
| 61 |
- // Contains returns whether the given items |
|
| 62 |
- // are all in the set. |
|
| 63 |
- Contains(val ...T) bool |
|
| 64 |
- |
|
| 65 |
- // ContainsOne returns whether the given item |
|
| 66 |
- // is in the set. |
|
| 67 |
- // |
|
| 68 |
- // Contains may cause the argument to escape to the heap. |
|
| 69 |
- // See: https://github.com/deckarep/golang-set/issues/118 |
|
| 70 |
- ContainsOne(val T) bool |
|
| 71 |
- |
|
| 72 |
- // ContainsAny returns whether at least one of the |
|
| 73 |
- // given items are in the set. |
|
| 74 |
- ContainsAny(val ...T) bool |
|
| 75 |
- |
|
| 76 |
- // ContainsAnyElement returns whether at least one of the |
|
| 77 |
- // given element are in the set. |
|
| 78 |
- ContainsAnyElement(other Set[T]) bool |
|
| 79 |
- |
|
| 80 |
- // Difference returns the difference between this set |
|
| 81 |
- // and other. The returned set will contain |
|
| 82 |
- // all elements of this set that are not also |
|
| 83 |
- // elements of other. |
|
| 84 |
- // |
|
| 85 |
- // Note that the argument to Difference |
|
| 86 |
- // must be of the same type as the receiver |
|
| 87 |
- // of the method. Otherwise, Difference will |
|
| 88 |
- // panic. |
|
| 89 |
- Difference(other Set[T]) Set[T] |
|
| 90 |
- |
|
| 91 |
- // Equal determines if two sets are equal to each |
|
| 92 |
- // other. If they have the same cardinality |
|
| 93 |
- // and contain the same elements, they are |
|
| 94 |
- // considered equal. The order in which |
|
| 95 |
- // the elements were added is irrelevant. |
|
| 96 |
- // |
|
| 97 |
- // Note that the argument to Equal must be |
|
| 98 |
- // of the same type as the receiver of the |
|
| 99 |
- // method. Otherwise, Equal will panic. |
|
| 100 |
- Equal(other Set[T]) bool |
|
| 101 |
- |
|
| 102 |
- // Intersect returns a new set containing only the elements |
|
| 103 |
- // that exist only in both sets. |
|
| 104 |
- // |
|
| 105 |
- // Note that the argument to Intersect |
|
| 106 |
- // must be of the same type as the receiver |
|
| 107 |
- // of the method. Otherwise, Intersect will |
|
| 108 |
- // panic. |
|
| 109 |
- Intersect(other Set[T]) Set[T] |
|
| 110 |
- |
|
| 111 |
- // IsEmpty determines if there are elements in the set. |
|
| 112 |
- IsEmpty() bool |
|
| 113 |
- |
|
| 114 |
- // IsProperSubset determines if every element in this set is in |
|
| 115 |
- // the other set but the two sets are not equal. |
|
| 116 |
- // |
|
| 117 |
- // Note that the argument to IsProperSubset |
|
| 118 |
- // must be of the same type as the receiver |
|
| 119 |
- // of the method. Otherwise, IsProperSubset |
|
| 120 |
- // will panic. |
|
| 121 |
- IsProperSubset(other Set[T]) bool |
|
| 122 |
- |
|
| 123 |
- // IsProperSuperset determines if every element in the other set |
|
| 124 |
- // is in this set but the two sets are not |
|
| 125 |
- // equal. |
|
| 126 |
- // |
|
| 127 |
- // Note that the argument to IsSuperset |
|
| 128 |
- // must be of the same type as the receiver |
|
| 129 |
- // of the method. Otherwise, IsSuperset will |
|
| 130 |
- // panic. |
|
| 131 |
- IsProperSuperset(other Set[T]) bool |
|
| 132 |
- |
|
| 133 |
- // IsSubset determines if every element in this set is in |
|
| 134 |
- // the other set. |
|
| 135 |
- // |
|
| 136 |
- // Note that the argument to IsSubset |
|
| 137 |
- // must be of the same type as the receiver |
|
| 138 |
- // of the method. Otherwise, IsSubset will |
|
| 139 |
- // panic. |
|
| 140 |
- IsSubset(other Set[T]) bool |
|
| 141 |
- |
|
| 142 |
- // IsSuperset determines if every element in the other set |
|
| 143 |
- // is in this set. |
|
| 144 |
- // |
|
| 145 |
- // Note that the argument to IsSuperset |
|
| 146 |
- // must be of the same type as the receiver |
|
| 147 |
- // of the method. Otherwise, IsSuperset will |
|
| 148 |
- // panic. |
|
| 149 |
- IsSuperset(other Set[T]) bool |
|
| 150 |
- |
|
| 151 |
- // Each iterates over elements and executes the passed func against each element. |
|
| 152 |
- // If passed func returns true, stop iteration at the time. |
|
| 153 |
- Each(func(T) bool) |
|
| 154 |
- |
|
| 155 |
- // Iter returns a channel of elements that you can |
|
| 156 |
- // range over. |
|
| 157 |
- Iter() <-chan T |
|
| 158 |
- |
|
| 159 |
- // Iterator returns an Iterator object that you can |
|
| 160 |
- // use to range over the set. |
|
| 161 |
- Iterator() *Iterator[T] |
|
| 162 |
- |
|
| 163 |
- // Remove removes a single element from the set. |
|
| 164 |
- Remove(i T) |
|
| 165 |
- |
|
| 166 |
- // RemoveAll removes multiple elements from the set. |
|
| 167 |
- RemoveAll(i ...T) |
|
| 168 |
- |
|
| 169 |
- // String provides a convenient string representation |
|
| 170 |
- // of the current state of the set. |
|
| 171 |
- String() string |
|
| 172 |
- |
|
| 173 |
- // SymmetricDifference returns a new set with all elements which are |
|
| 174 |
- // in either this set or the other set but not in both. |
|
| 175 |
- // |
|
| 176 |
- // Note that the argument to SymmetricDifference |
|
| 177 |
- // must be of the same type as the receiver |
|
| 178 |
- // of the method. Otherwise, SymmetricDifference |
|
| 179 |
- // will panic. |
|
| 180 |
- SymmetricDifference(other Set[T]) Set[T] |
|
| 181 |
- |
|
| 182 |
- // Union returns a new set with all elements in both sets. |
|
| 183 |
- // |
|
| 184 |
- // Note that the argument to Union must be of the |
|
| 185 |
- // same type as the receiver of the method. |
|
| 186 |
- // Otherwise, Union will panic. |
|
| 187 |
- Union(other Set[T]) Set[T] |
|
| 188 |
- |
|
| 189 |
- // Pop removes and returns an arbitrary item from the set. |
|
| 190 |
- Pop() (T, bool) |
|
| 191 |
- |
|
| 192 |
- // ToSlice returns the members of the set as a slice. |
|
| 193 |
- ToSlice() []T |
|
| 194 |
- |
|
| 195 |
- // MarshalJSON will marshal the set into a JSON-based representation. |
|
| 196 |
- MarshalJSON() ([]byte, error) |
|
| 197 |
- |
|
| 198 |
- // UnmarshalJSON will unmarshal a JSON-based byte slice into a full Set datastructure. |
|
| 199 |
- // For this to work, set subtypes must implemented the Marshal/Unmarshal interface. |
|
| 200 |
- UnmarshalJSON(b []byte) error |
|
| 201 |
-} |
|
| 202 |
- |
|
| 203 |
-// NewSet creates and returns a new set with the given elements. |
|
| 204 |
-// Operations on the resulting set are thread-safe. |
|
| 205 |
-func NewSet[T comparable](vals ...T) Set[T] {
|
|
| 206 |
- s := newThreadSafeSetWithSize[T](len(vals)) |
|
| 207 |
- for _, item := range vals {
|
|
| 208 |
- s.Add(item) |
|
| 209 |
- } |
|
| 210 |
- return s |
|
| 211 |
-} |
|
| 212 |
- |
|
| 213 |
-// NewSetWithSize creates and returns a reference to an empty set with a specified |
|
| 214 |
-// capacity. Operations on the resulting set are thread-safe. |
|
| 215 |
-func NewSetWithSize[T comparable](cardinality int) Set[T] {
|
|
| 216 |
- s := newThreadSafeSetWithSize[T](cardinality) |
|
| 217 |
- return s |
|
| 218 |
-} |
|
| 219 |
- |
|
| 220 |
-// NewThreadUnsafeSet creates and returns a new set with the given elements. |
|
| 221 |
-// Operations on the resulting set are not thread-safe. |
|
| 222 |
-func NewThreadUnsafeSet[T comparable](vals ...T) Set[T] {
|
|
| 223 |
- s := newThreadUnsafeSetWithSize[T](len(vals)) |
|
| 224 |
- for _, item := range vals {
|
|
| 225 |
- s.Add(item) |
|
| 226 |
- } |
|
| 227 |
- return s |
|
| 228 |
-} |
|
| 229 |
- |
|
| 230 |
-// NewThreadUnsafeSetWithSize creates and returns a reference to an empty set with |
|
| 231 |
-// a specified capacity. Operations on the resulting set are not thread-safe. |
|
| 232 |
-func NewThreadUnsafeSetWithSize[T comparable](cardinality int) Set[T] {
|
|
| 233 |
- s := newThreadUnsafeSetWithSize[T](cardinality) |
|
| 234 |
- return s |
|
| 235 |
-} |
|
| 236 |
- |
|
| 237 |
-// NewSetFromMapKeys creates and returns a new set with the given keys of the map. |
|
| 238 |
-// Operations on the resulting set are thread-safe. |
|
| 239 |
-func NewSetFromMapKeys[T comparable, V any](val map[T]V) Set[T] {
|
|
| 240 |
- s := NewSetWithSize[T](len(val)) |
|
| 241 |
- |
|
| 242 |
- for k := range val {
|
|
| 243 |
- s.Add(k) |
|
| 244 |
- } |
|
| 245 |
- |
|
| 246 |
- return s |
|
| 247 |
-} |
|
| 248 |
- |
|
| 249 |
-// NewThreadUnsafeSetFromMapKeys creates and returns a new set with the given keys of the map. |
|
| 250 |
-// Operations on the resulting set are not thread-safe. |
|
| 251 |
-func NewThreadUnsafeSetFromMapKeys[T comparable, V any](val map[T]V) Set[T] {
|
|
| 252 |
- s := NewThreadUnsafeSetWithSize[T](len(val)) |
|
| 253 |
- |
|
| 254 |
- for k := range val {
|
|
| 255 |
- s.Add(k) |
|
| 256 |
- } |
|
| 257 |
- |
|
| 258 |
- return s |
|
| 259 |
-} |
|
| 260 |
- |
|
| 261 |
-// Elements returns an iterator that yields the elements of the set. Starting |
|
| 262 |
-// with Go 1.23, users can use a for loop to iterate over it. |
|
| 263 |
-func Elements[T comparable](s Set[T]) func(func(element T) bool) {
|
|
| 264 |
- return func(yield func(element T) bool) {
|
|
| 265 |
- s.Each(func(t T) bool {
|
|
| 266 |
- return !yield(t) |
|
| 267 |
- }) |
|
| 268 |
- } |
|
| 269 |
-} |
| 270 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,42 +0,0 @@ |
| 1 |
-//go:build go1.21 |
|
| 2 |
-// +build go1.21 |
|
| 3 |
- |
|
| 4 |
-/* |
|
| 5 |
-Open Source Initiative OSI - The MIT License (MIT):Licensing |
|
| 6 |
- |
|
| 7 |
-The MIT License (MIT) |
|
| 8 |
-Copyright (c) 2013 - 2023 Ralph Caraveo (deckarep@gmail.com) |
|
| 9 |
- |
|
| 10 |
-Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
| 11 |
-this software and associated documentation files (the "Software"), to deal in |
|
| 12 |
-the Software without restriction, including without limitation the rights to |
|
| 13 |
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|
| 14 |
-of the Software, and to permit persons to whom the Software is furnished to do |
|
| 15 |
-so, subject to the following conditions: |
|
| 16 |
- |
|
| 17 |
-The above copyright notice and this permission notice shall be included in all |
|
| 18 |
-copies or substantial portions of the Software. |
|
| 19 |
- |
|
| 20 |
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 21 |
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
| 22 |
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
| 23 |
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
| 24 |
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
| 25 |
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
| 26 |
-SOFTWARE. |
|
| 27 |
-*/ |
|
| 28 |
- |
|
| 29 |
-package mapset |
|
| 30 |
- |
|
| 31 |
-import ( |
|
| 32 |
- "cmp" |
|
| 33 |
- "slices" |
|
| 34 |
-) |
|
| 35 |
- |
|
| 36 |
-// Sorted returns a sorted slice of a set of any ordered type in ascending order. |
|
| 37 |
-// When sorting floating-point numbers, NaNs are ordered before other values. |
|
| 38 |
-func Sorted[E cmp.Ordered](set Set[E]) []E {
|
|
| 39 |
- s := set.ToSlice() |
|
| 40 |
- slices.Sort(s) |
|
| 41 |
- return s |
|
| 42 |
-} |
| 43 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,312 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
-Open Source Initiative OSI - The MIT License (MIT):Licensing |
|
| 3 |
- |
|
| 4 |
-The MIT License (MIT) |
|
| 5 |
-Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) |
|
| 6 |
- |
|
| 7 |
-Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
| 8 |
-this software and associated documentation files (the "Software"), to deal in |
|
| 9 |
-the Software without restriction, including without limitation the rights to |
|
| 10 |
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|
| 11 |
-of the Software, and to permit persons to whom the Software is furnished to do |
|
| 12 |
-so, subject to the following conditions: |
|
| 13 |
- |
|
| 14 |
-The above copyright notice and this permission notice shall be included in all |
|
| 15 |
-copies or substantial portions of the Software. |
|
| 16 |
- |
|
| 17 |
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 18 |
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
| 19 |
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
| 20 |
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
| 21 |
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
| 22 |
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
| 23 |
-SOFTWARE. |
|
| 24 |
-*/ |
|
| 25 |
- |
|
| 26 |
-package mapset |
|
| 27 |
- |
|
| 28 |
-import "sync" |
|
| 29 |
- |
|
| 30 |
-type threadSafeSet[T comparable] struct {
|
|
| 31 |
- sync.RWMutex |
|
| 32 |
- uss *threadUnsafeSet[T] |
|
| 33 |
-} |
|
| 34 |
- |
|
| 35 |
-func newThreadSafeSet[T comparable]() *threadSafeSet[T] {
|
|
| 36 |
- return &threadSafeSet[T]{
|
|
| 37 |
- uss: newThreadUnsafeSet[T](), |
|
| 38 |
- } |
|
| 39 |
-} |
|
| 40 |
- |
|
| 41 |
-func newThreadSafeSetWithSize[T comparable](cardinality int) *threadSafeSet[T] {
|
|
| 42 |
- return &threadSafeSet[T]{
|
|
| 43 |
- uss: newThreadUnsafeSetWithSize[T](cardinality), |
|
| 44 |
- } |
|
| 45 |
-} |
|
| 46 |
- |
|
| 47 |
-func (t *threadSafeSet[T]) Add(v T) bool {
|
|
| 48 |
- t.Lock() |
|
| 49 |
- ret := t.uss.Add(v) |
|
| 50 |
- t.Unlock() |
|
| 51 |
- return ret |
|
| 52 |
-} |
|
| 53 |
- |
|
| 54 |
-func (t *threadSafeSet[T]) Append(v ...T) int {
|
|
| 55 |
- t.Lock() |
|
| 56 |
- ret := t.uss.Append(v...) |
|
| 57 |
- t.Unlock() |
|
| 58 |
- return ret |
|
| 59 |
-} |
|
| 60 |
- |
|
| 61 |
-func (t *threadSafeSet[T]) Contains(v ...T) bool {
|
|
| 62 |
- t.RLock() |
|
| 63 |
- ret := t.uss.Contains(v...) |
|
| 64 |
- t.RUnlock() |
|
| 65 |
- |
|
| 66 |
- return ret |
|
| 67 |
-} |
|
| 68 |
- |
|
| 69 |
-func (t *threadSafeSet[T]) ContainsOne(v T) bool {
|
|
| 70 |
- t.RLock() |
|
| 71 |
- ret := t.uss.ContainsOne(v) |
|
| 72 |
- t.RUnlock() |
|
| 73 |
- |
|
| 74 |
- return ret |
|
| 75 |
-} |
|
| 76 |
- |
|
| 77 |
-func (t *threadSafeSet[T]) ContainsAny(v ...T) bool {
|
|
| 78 |
- t.RLock() |
|
| 79 |
- ret := t.uss.ContainsAny(v...) |
|
| 80 |
- t.RUnlock() |
|
| 81 |
- |
|
| 82 |
- return ret |
|
| 83 |
-} |
|
| 84 |
- |
|
| 85 |
-func (t *threadSafeSet[T]) ContainsAnyElement(other Set[T]) bool {
|
|
| 86 |
- o := other.(*threadSafeSet[T]) |
|
| 87 |
- |
|
| 88 |
- t.RLock() |
|
| 89 |
- o.RLock() |
|
| 90 |
- |
|
| 91 |
- ret := t.uss.ContainsAnyElement(o.uss) |
|
| 92 |
- |
|
| 93 |
- t.RUnlock() |
|
| 94 |
- o.RUnlock() |
|
| 95 |
- return ret |
|
| 96 |
-} |
|
| 97 |
- |
|
| 98 |
-func (t *threadSafeSet[T]) IsEmpty() bool {
|
|
| 99 |
- return t.Cardinality() == 0 |
|
| 100 |
-} |
|
| 101 |
- |
|
| 102 |
-func (t *threadSafeSet[T]) IsSubset(other Set[T]) bool {
|
|
| 103 |
- o := other.(*threadSafeSet[T]) |
|
| 104 |
- |
|
| 105 |
- t.RLock() |
|
| 106 |
- o.RLock() |
|
| 107 |
- |
|
| 108 |
- ret := t.uss.IsSubset(o.uss) |
|
| 109 |
- t.RUnlock() |
|
| 110 |
- o.RUnlock() |
|
| 111 |
- return ret |
|
| 112 |
-} |
|
| 113 |
- |
|
| 114 |
-func (t *threadSafeSet[T]) IsProperSubset(other Set[T]) bool {
|
|
| 115 |
- o := other.(*threadSafeSet[T]) |
|
| 116 |
- |
|
| 117 |
- t.RLock() |
|
| 118 |
- defer t.RUnlock() |
|
| 119 |
- o.RLock() |
|
| 120 |
- defer o.RUnlock() |
|
| 121 |
- |
|
| 122 |
- return t.uss.IsProperSubset(o.uss) |
|
| 123 |
-} |
|
| 124 |
- |
|
| 125 |
-func (t *threadSafeSet[T]) IsSuperset(other Set[T]) bool {
|
|
| 126 |
- return other.IsSubset(t) |
|
| 127 |
-} |
|
| 128 |
- |
|
| 129 |
-func (t *threadSafeSet[T]) IsProperSuperset(other Set[T]) bool {
|
|
| 130 |
- return other.IsProperSubset(t) |
|
| 131 |
-} |
|
| 132 |
- |
|
| 133 |
-func (t *threadSafeSet[T]) Union(other Set[T]) Set[T] {
|
|
| 134 |
- o := other.(*threadSafeSet[T]) |
|
| 135 |
- |
|
| 136 |
- t.RLock() |
|
| 137 |
- o.RLock() |
|
| 138 |
- |
|
| 139 |
- unsafeUnion := t.uss.Union(o.uss).(*threadUnsafeSet[T]) |
|
| 140 |
- ret := &threadSafeSet[T]{uss: unsafeUnion}
|
|
| 141 |
- t.RUnlock() |
|
| 142 |
- o.RUnlock() |
|
| 143 |
- return ret |
|
| 144 |
-} |
|
| 145 |
- |
|
| 146 |
-func (t *threadSafeSet[T]) Intersect(other Set[T]) Set[T] {
|
|
| 147 |
- o := other.(*threadSafeSet[T]) |
|
| 148 |
- |
|
| 149 |
- t.RLock() |
|
| 150 |
- o.RLock() |
|
| 151 |
- |
|
| 152 |
- unsafeIntersection := t.uss.Intersect(o.uss).(*threadUnsafeSet[T]) |
|
| 153 |
- ret := &threadSafeSet[T]{uss: unsafeIntersection}
|
|
| 154 |
- t.RUnlock() |
|
| 155 |
- o.RUnlock() |
|
| 156 |
- return ret |
|
| 157 |
-} |
|
| 158 |
- |
|
| 159 |
-func (t *threadSafeSet[T]) Difference(other Set[T]) Set[T] {
|
|
| 160 |
- o := other.(*threadSafeSet[T]) |
|
| 161 |
- |
|
| 162 |
- t.RLock() |
|
| 163 |
- o.RLock() |
|
| 164 |
- |
|
| 165 |
- unsafeDifference := t.uss.Difference(o.uss).(*threadUnsafeSet[T]) |
|
| 166 |
- ret := &threadSafeSet[T]{uss: unsafeDifference}
|
|
| 167 |
- t.RUnlock() |
|
| 168 |
- o.RUnlock() |
|
| 169 |
- return ret |
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 |
-func (t *threadSafeSet[T]) SymmetricDifference(other Set[T]) Set[T] {
|
|
| 173 |
- o := other.(*threadSafeSet[T]) |
|
| 174 |
- |
|
| 175 |
- t.RLock() |
|
| 176 |
- o.RLock() |
|
| 177 |
- |
|
| 178 |
- unsafeDifference := t.uss.SymmetricDifference(o.uss).(*threadUnsafeSet[T]) |
|
| 179 |
- ret := &threadSafeSet[T]{uss: unsafeDifference}
|
|
| 180 |
- t.RUnlock() |
|
| 181 |
- o.RUnlock() |
|
| 182 |
- return ret |
|
| 183 |
-} |
|
| 184 |
- |
|
| 185 |
-func (t *threadSafeSet[T]) Clear() {
|
|
| 186 |
- t.Lock() |
|
| 187 |
- t.uss.Clear() |
|
| 188 |
- t.Unlock() |
|
| 189 |
-} |
|
| 190 |
- |
|
| 191 |
-func (t *threadSafeSet[T]) Remove(v T) {
|
|
| 192 |
- t.Lock() |
|
| 193 |
- delete(*t.uss, v) |
|
| 194 |
- t.Unlock() |
|
| 195 |
-} |
|
| 196 |
- |
|
| 197 |
-func (t *threadSafeSet[T]) RemoveAll(i ...T) {
|
|
| 198 |
- t.Lock() |
|
| 199 |
- t.uss.RemoveAll(i...) |
|
| 200 |
- t.Unlock() |
|
| 201 |
-} |
|
| 202 |
- |
|
| 203 |
-func (t *threadSafeSet[T]) Cardinality() int {
|
|
| 204 |
- t.RLock() |
|
| 205 |
- defer t.RUnlock() |
|
| 206 |
- return len(*t.uss) |
|
| 207 |
-} |
|
| 208 |
- |
|
| 209 |
-func (t *threadSafeSet[T]) Each(cb func(T) bool) {
|
|
| 210 |
- t.RLock() |
|
| 211 |
- for elem := range *t.uss {
|
|
| 212 |
- if cb(elem) {
|
|
| 213 |
- break |
|
| 214 |
- } |
|
| 215 |
- } |
|
| 216 |
- t.RUnlock() |
|
| 217 |
-} |
|
| 218 |
- |
|
| 219 |
-func (t *threadSafeSet[T]) Iter() <-chan T {
|
|
| 220 |
- ch := make(chan T) |
|
| 221 |
- go func() {
|
|
| 222 |
- t.RLock() |
|
| 223 |
- |
|
| 224 |
- for elem := range *t.uss {
|
|
| 225 |
- ch <- elem |
|
| 226 |
- } |
|
| 227 |
- close(ch) |
|
| 228 |
- t.RUnlock() |
|
| 229 |
- }() |
|
| 230 |
- |
|
| 231 |
- return ch |
|
| 232 |
-} |
|
| 233 |
- |
|
| 234 |
-func (t *threadSafeSet[T]) Iterator() *Iterator[T] {
|
|
| 235 |
- iterator, ch, stopCh := newIterator[T]() |
|
| 236 |
- |
|
| 237 |
- go func() {
|
|
| 238 |
- t.RLock() |
|
| 239 |
- L: |
|
| 240 |
- for elem := range *t.uss {
|
|
| 241 |
- select {
|
|
| 242 |
- case <-stopCh: |
|
| 243 |
- break L |
|
| 244 |
- case ch <- elem: |
|
| 245 |
- } |
|
| 246 |
- } |
|
| 247 |
- close(ch) |
|
| 248 |
- t.RUnlock() |
|
| 249 |
- }() |
|
| 250 |
- |
|
| 251 |
- return iterator |
|
| 252 |
-} |
|
| 253 |
- |
|
| 254 |
-func (t *threadSafeSet[T]) Equal(other Set[T]) bool {
|
|
| 255 |
- o := other.(*threadSafeSet[T]) |
|
| 256 |
- |
|
| 257 |
- t.RLock() |
|
| 258 |
- o.RLock() |
|
| 259 |
- |
|
| 260 |
- ret := t.uss.Equal(o.uss) |
|
| 261 |
- t.RUnlock() |
|
| 262 |
- o.RUnlock() |
|
| 263 |
- return ret |
|
| 264 |
-} |
|
| 265 |
- |
|
| 266 |
-func (t *threadSafeSet[T]) Clone() Set[T] {
|
|
| 267 |
- t.RLock() |
|
| 268 |
- |
|
| 269 |
- unsafeClone := t.uss.Clone().(*threadUnsafeSet[T]) |
|
| 270 |
- ret := &threadSafeSet[T]{uss: unsafeClone}
|
|
| 271 |
- t.RUnlock() |
|
| 272 |
- return ret |
|
| 273 |
-} |
|
| 274 |
- |
|
| 275 |
-func (t *threadSafeSet[T]) String() string {
|
|
| 276 |
- t.RLock() |
|
| 277 |
- ret := t.uss.String() |
|
| 278 |
- t.RUnlock() |
|
| 279 |
- return ret |
|
| 280 |
-} |
|
| 281 |
- |
|
| 282 |
-func (t *threadSafeSet[T]) Pop() (T, bool) {
|
|
| 283 |
- t.Lock() |
|
| 284 |
- defer t.Unlock() |
|
| 285 |
- return t.uss.Pop() |
|
| 286 |
-} |
|
| 287 |
- |
|
| 288 |
-func (t *threadSafeSet[T]) ToSlice() []T {
|
|
| 289 |
- keys := make([]T, 0, t.Cardinality()) |
|
| 290 |
- t.RLock() |
|
| 291 |
- for elem := range *t.uss {
|
|
| 292 |
- keys = append(keys, elem) |
|
| 293 |
- } |
|
| 294 |
- t.RUnlock() |
|
| 295 |
- return keys |
|
| 296 |
-} |
|
| 297 |
- |
|
| 298 |
-func (t *threadSafeSet[T]) MarshalJSON() ([]byte, error) {
|
|
| 299 |
- t.RLock() |
|
| 300 |
- b, err := t.uss.MarshalJSON() |
|
| 301 |
- t.RUnlock() |
|
| 302 |
- |
|
| 303 |
- return b, err |
|
| 304 |
-} |
|
| 305 |
- |
|
| 306 |
-func (t *threadSafeSet[T]) UnmarshalJSON(p []byte) error {
|
|
| 307 |
- t.RLock() |
|
| 308 |
- err := t.uss.UnmarshalJSON(p) |
|
| 309 |
- t.RUnlock() |
|
| 310 |
- |
|
| 311 |
- return err |
|
| 312 |
-} |
| 313 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,352 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
-Open Source Initiative OSI - The MIT License (MIT):Licensing |
|
| 3 |
- |
|
| 4 |
-The MIT License (MIT) |
|
| 5 |
-Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) |
|
| 6 |
- |
|
| 7 |
-Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
| 8 |
-this software and associated documentation files (the "Software"), to deal in |
|
| 9 |
-the Software without restriction, including without limitation the rights to |
|
| 10 |
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|
| 11 |
-of the Software, and to permit persons to whom the Software is furnished to do |
|
| 12 |
-so, subject to the following conditions: |
|
| 13 |
- |
|
| 14 |
-The above copyright notice and this permission notice shall be included in all |
|
| 15 |
-copies or substantial portions of the Software. |
|
| 16 |
- |
|
| 17 |
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 18 |
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
| 19 |
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
| 20 |
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
| 21 |
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
| 22 |
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
| 23 |
-SOFTWARE. |
|
| 24 |
-*/ |
|
| 25 |
- |
|
| 26 |
-package mapset |
|
| 27 |
- |
|
| 28 |
-import ( |
|
| 29 |
- "encoding/json" |
|
| 30 |
- "fmt" |
|
| 31 |
- "strings" |
|
| 32 |
-) |
|
| 33 |
- |
|
| 34 |
-type threadUnsafeSet[T comparable] map[T]struct{}
|
|
| 35 |
- |
|
| 36 |
-// Assert concrete type:threadUnsafeSet adheres to Set interface. |
|
| 37 |
-var _ Set[string] = (*threadUnsafeSet[string])(nil) |
|
| 38 |
- |
|
| 39 |
-func newThreadUnsafeSet[T comparable]() *threadUnsafeSet[T] {
|
|
| 40 |
- t := make(threadUnsafeSet[T]) |
|
| 41 |
- return &t |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 |
-func newThreadUnsafeSetWithSize[T comparable](cardinality int) *threadUnsafeSet[T] {
|
|
| 45 |
- t := make(threadUnsafeSet[T], cardinality) |
|
| 46 |
- return &t |
|
| 47 |
-} |
|
| 48 |
- |
|
| 49 |
-func (s threadUnsafeSet[T]) Add(v T) bool {
|
|
| 50 |
- prevLen := len(s) |
|
| 51 |
- s[v] = struct{}{}
|
|
| 52 |
- return prevLen != len(s) |
|
| 53 |
-} |
|
| 54 |
- |
|
| 55 |
-func (s *threadUnsafeSet[T]) Append(v ...T) int {
|
|
| 56 |
- prevLen := len(*s) |
|
| 57 |
- for _, val := range v {
|
|
| 58 |
- (*s)[val] = struct{}{}
|
|
| 59 |
- } |
|
| 60 |
- return len(*s) - prevLen |
|
| 61 |
-} |
|
| 62 |
- |
|
| 63 |
-// private version of Add which doesn't return a value |
|
| 64 |
-func (s *threadUnsafeSet[T]) add(v T) {
|
|
| 65 |
- (*s)[v] = struct{}{}
|
|
| 66 |
-} |
|
| 67 |
- |
|
| 68 |
-func (s *threadUnsafeSet[T]) Cardinality() int {
|
|
| 69 |
- return len(*s) |
|
| 70 |
-} |
|
| 71 |
- |
|
| 72 |
-func (s *threadUnsafeSet[T]) Clear() {
|
|
| 73 |
- // Constructions like this are optimised by compiler, and replaced by |
|
| 74 |
- // mapclear() function, defined in |
|
| 75 |
- // https://github.com/golang/go/blob/29bbca5c2c1ad41b2a9747890d183b6dd3a4ace4/src/runtime/map.go#L993) |
|
| 76 |
- for key := range *s {
|
|
| 77 |
- delete(*s, key) |
|
| 78 |
- } |
|
| 79 |
-} |
|
| 80 |
- |
|
| 81 |
-func (s *threadUnsafeSet[T]) Clone() Set[T] {
|
|
| 82 |
- clonedSet := newThreadUnsafeSetWithSize[T](s.Cardinality()) |
|
| 83 |
- for elem := range *s {
|
|
| 84 |
- clonedSet.add(elem) |
|
| 85 |
- } |
|
| 86 |
- return clonedSet |
|
| 87 |
-} |
|
| 88 |
- |
|
| 89 |
-func (s *threadUnsafeSet[T]) Contains(v ...T) bool {
|
|
| 90 |
- for _, val := range v {
|
|
| 91 |
- if _, ok := (*s)[val]; !ok {
|
|
| 92 |
- return false |
|
| 93 |
- } |
|
| 94 |
- } |
|
| 95 |
- return true |
|
| 96 |
-} |
|
| 97 |
- |
|
| 98 |
-func (s *threadUnsafeSet[T]) ContainsOne(v T) bool {
|
|
| 99 |
- _, ok := (*s)[v] |
|
| 100 |
- return ok |
|
| 101 |
-} |
|
| 102 |
- |
|
| 103 |
-func (s *threadUnsafeSet[T]) ContainsAny(v ...T) bool {
|
|
| 104 |
- for _, val := range v {
|
|
| 105 |
- if _, ok := (*s)[val]; ok {
|
|
| 106 |
- return true |
|
| 107 |
- } |
|
| 108 |
- } |
|
| 109 |
- return false |
|
| 110 |
-} |
|
| 111 |
- |
|
| 112 |
-func (s *threadUnsafeSet[T]) ContainsAnyElement(other Set[T]) bool {
|
|
| 113 |
- o := other.(*threadUnsafeSet[T]) |
|
| 114 |
- |
|
| 115 |
- // loop over smaller set |
|
| 116 |
- if s.Cardinality() < other.Cardinality() {
|
|
| 117 |
- for elem := range *s {
|
|
| 118 |
- if o.contains(elem) {
|
|
| 119 |
- return true |
|
| 120 |
- } |
|
| 121 |
- } |
|
| 122 |
- } else {
|
|
| 123 |
- for elem := range *o {
|
|
| 124 |
- if s.contains(elem) {
|
|
| 125 |
- return true |
|
| 126 |
- } |
|
| 127 |
- } |
|
| 128 |
- } |
|
| 129 |
- return false |
|
| 130 |
-} |
|
| 131 |
- |
|
| 132 |
-// private version of Contains for a single element v |
|
| 133 |
-func (s *threadUnsafeSet[T]) contains(v T) (ok bool) {
|
|
| 134 |
- _, ok = (*s)[v] |
|
| 135 |
- return ok |
|
| 136 |
-} |
|
| 137 |
- |
|
| 138 |
-func (s *threadUnsafeSet[T]) Difference(other Set[T]) Set[T] {
|
|
| 139 |
- o := other.(*threadUnsafeSet[T]) |
|
| 140 |
- |
|
| 141 |
- diff := newThreadUnsafeSet[T]() |
|
| 142 |
- for elem := range *s {
|
|
| 143 |
- if !o.contains(elem) {
|
|
| 144 |
- diff.add(elem) |
|
| 145 |
- } |
|
| 146 |
- } |
|
| 147 |
- return diff |
|
| 148 |
-} |
|
| 149 |
- |
|
| 150 |
-func (s *threadUnsafeSet[T]) Each(cb func(T) bool) {
|
|
| 151 |
- for elem := range *s {
|
|
| 152 |
- if cb(elem) {
|
|
| 153 |
- break |
|
| 154 |
- } |
|
| 155 |
- } |
|
| 156 |
-} |
|
| 157 |
- |
|
| 158 |
-func (s *threadUnsafeSet[T]) Equal(other Set[T]) bool {
|
|
| 159 |
- o := other.(*threadUnsafeSet[T]) |
|
| 160 |
- |
|
| 161 |
- if s.Cardinality() != other.Cardinality() {
|
|
| 162 |
- return false |
|
| 163 |
- } |
|
| 164 |
- for elem := range *s {
|
|
| 165 |
- if !o.contains(elem) {
|
|
| 166 |
- return false |
|
| 167 |
- } |
|
| 168 |
- } |
|
| 169 |
- return true |
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 |
-func (s *threadUnsafeSet[T]) Intersect(other Set[T]) Set[T] {
|
|
| 173 |
- o := other.(*threadUnsafeSet[T]) |
|
| 174 |
- |
|
| 175 |
- intersection := newThreadUnsafeSet[T]() |
|
| 176 |
- // loop over smaller set |
|
| 177 |
- if s.Cardinality() < other.Cardinality() {
|
|
| 178 |
- for elem := range *s {
|
|
| 179 |
- if o.contains(elem) {
|
|
| 180 |
- intersection.add(elem) |
|
| 181 |
- } |
|
| 182 |
- } |
|
| 183 |
- } else {
|
|
| 184 |
- for elem := range *o {
|
|
| 185 |
- if s.contains(elem) {
|
|
| 186 |
- intersection.add(elem) |
|
| 187 |
- } |
|
| 188 |
- } |
|
| 189 |
- } |
|
| 190 |
- return intersection |
|
| 191 |
-} |
|
| 192 |
- |
|
| 193 |
-func (s *threadUnsafeSet[T]) IsEmpty() bool {
|
|
| 194 |
- return s.Cardinality() == 0 |
|
| 195 |
-} |
|
| 196 |
- |
|
| 197 |
-func (s *threadUnsafeSet[T]) IsProperSubset(other Set[T]) bool {
|
|
| 198 |
- return s.Cardinality() < other.Cardinality() && s.IsSubset(other) |
|
| 199 |
-} |
|
| 200 |
- |
|
| 201 |
-func (s *threadUnsafeSet[T]) IsProperSuperset(other Set[T]) bool {
|
|
| 202 |
- return s.Cardinality() > other.Cardinality() && s.IsSuperset(other) |
|
| 203 |
-} |
|
| 204 |
- |
|
| 205 |
-func (s *threadUnsafeSet[T]) IsSubset(other Set[T]) bool {
|
|
| 206 |
- o := other.(*threadUnsafeSet[T]) |
|
| 207 |
- if s.Cardinality() > other.Cardinality() {
|
|
| 208 |
- return false |
|
| 209 |
- } |
|
| 210 |
- for elem := range *s {
|
|
| 211 |
- if !o.contains(elem) {
|
|
| 212 |
- return false |
|
| 213 |
- } |
|
| 214 |
- } |
|
| 215 |
- return true |
|
| 216 |
-} |
|
| 217 |
- |
|
| 218 |
-func (s *threadUnsafeSet[T]) IsSuperset(other Set[T]) bool {
|
|
| 219 |
- return other.IsSubset(s) |
|
| 220 |
-} |
|
| 221 |
- |
|
| 222 |
-func (s *threadUnsafeSet[T]) Iter() <-chan T {
|
|
| 223 |
- ch := make(chan T) |
|
| 224 |
- go func() {
|
|
| 225 |
- for elem := range *s {
|
|
| 226 |
- ch <- elem |
|
| 227 |
- } |
|
| 228 |
- close(ch) |
|
| 229 |
- }() |
|
| 230 |
- |
|
| 231 |
- return ch |
|
| 232 |
-} |
|
| 233 |
- |
|
| 234 |
-func (s *threadUnsafeSet[T]) Iterator() *Iterator[T] {
|
|
| 235 |
- iterator, ch, stopCh := newIterator[T]() |
|
| 236 |
- |
|
| 237 |
- go func() {
|
|
| 238 |
- L: |
|
| 239 |
- for elem := range *s {
|
|
| 240 |
- select {
|
|
| 241 |
- case <-stopCh: |
|
| 242 |
- break L |
|
| 243 |
- case ch <- elem: |
|
| 244 |
- } |
|
| 245 |
- } |
|
| 246 |
- close(ch) |
|
| 247 |
- }() |
|
| 248 |
- |
|
| 249 |
- return iterator |
|
| 250 |
-} |
|
| 251 |
- |
|
| 252 |
-// Pop returns a popped item in case set is not empty, or nil-value of T |
|
| 253 |
-// if set is already empty |
|
| 254 |
-func (s *threadUnsafeSet[T]) Pop() (v T, ok bool) {
|
|
| 255 |
- for item := range *s {
|
|
| 256 |
- delete(*s, item) |
|
| 257 |
- return item, true |
|
| 258 |
- } |
|
| 259 |
- return v, false |
|
| 260 |
-} |
|
| 261 |
- |
|
| 262 |
-func (s threadUnsafeSet[T]) Remove(v T) {
|
|
| 263 |
- delete(s, v) |
|
| 264 |
-} |
|
| 265 |
- |
|
| 266 |
-func (s threadUnsafeSet[T]) RemoveAll(i ...T) {
|
|
| 267 |
- for _, elem := range i {
|
|
| 268 |
- delete(s, elem) |
|
| 269 |
- } |
|
| 270 |
-} |
|
| 271 |
- |
|
| 272 |
-func (s threadUnsafeSet[T]) String() string {
|
|
| 273 |
- items := make([]string, 0, len(s)) |
|
| 274 |
- |
|
| 275 |
- for elem := range s {
|
|
| 276 |
- items = append(items, fmt.Sprintf("%v", elem))
|
|
| 277 |
- } |
|
| 278 |
- return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
|
|
| 279 |
-} |
|
| 280 |
- |
|
| 281 |
-func (s *threadUnsafeSet[T]) SymmetricDifference(other Set[T]) Set[T] {
|
|
| 282 |
- o := other.(*threadUnsafeSet[T]) |
|
| 283 |
- |
|
| 284 |
- sd := newThreadUnsafeSet[T]() |
|
| 285 |
- for elem := range *s {
|
|
| 286 |
- if !o.contains(elem) {
|
|
| 287 |
- sd.add(elem) |
|
| 288 |
- } |
|
| 289 |
- } |
|
| 290 |
- for elem := range *o {
|
|
| 291 |
- if !s.contains(elem) {
|
|
| 292 |
- sd.add(elem) |
|
| 293 |
- } |
|
| 294 |
- } |
|
| 295 |
- return sd |
|
| 296 |
-} |
|
| 297 |
- |
|
| 298 |
-func (s threadUnsafeSet[T]) ToSlice() []T {
|
|
| 299 |
- keys := make([]T, 0, s.Cardinality()) |
|
| 300 |
- for elem := range s {
|
|
| 301 |
- keys = append(keys, elem) |
|
| 302 |
- } |
|
| 303 |
- |
|
| 304 |
- return keys |
|
| 305 |
-} |
|
| 306 |
- |
|
| 307 |
-func (s threadUnsafeSet[T]) Union(other Set[T]) Set[T] {
|
|
| 308 |
- o := other.(*threadUnsafeSet[T]) |
|
| 309 |
- |
|
| 310 |
- n := s.Cardinality() |
|
| 311 |
- if o.Cardinality() > n {
|
|
| 312 |
- n = o.Cardinality() |
|
| 313 |
- } |
|
| 314 |
- unionedSet := make(threadUnsafeSet[T], n) |
|
| 315 |
- |
|
| 316 |
- for elem := range s {
|
|
| 317 |
- unionedSet.add(elem) |
|
| 318 |
- } |
|
| 319 |
- for elem := range *o {
|
|
| 320 |
- unionedSet.add(elem) |
|
| 321 |
- } |
|
| 322 |
- return &unionedSet |
|
| 323 |
-} |
|
| 324 |
- |
|
| 325 |
-// MarshalJSON creates a JSON array from the set, it marshals all elements |
|
| 326 |
-func (s threadUnsafeSet[T]) MarshalJSON() ([]byte, error) {
|
|
| 327 |
- items := make([]string, 0, s.Cardinality()) |
|
| 328 |
- |
|
| 329 |
- for elem := range s {
|
|
| 330 |
- b, err := json.Marshal(elem) |
|
| 331 |
- if err != nil {
|
|
| 332 |
- return nil, err |
|
| 333 |
- } |
|
| 334 |
- |
|
| 335 |
- items = append(items, string(b)) |
|
| 336 |
- } |
|
| 337 |
- |
|
| 338 |
- return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil
|
|
| 339 |
-} |
|
| 340 |
- |
|
| 341 |
-// UnmarshalJSON recreates a set from a JSON array, it only decodes |
|
| 342 |
-// primitive types. Numbers are decoded as json.Number. |
|
| 343 |
-func (s *threadUnsafeSet[T]) UnmarshalJSON(b []byte) error {
|
|
| 344 |
- var i []T |
|
| 345 |
- err := json.Unmarshal(b, &i) |
|
| 346 |
- if err != nil {
|
|
| 347 |
- return err |
|
| 348 |
- } |
|
| 349 |
- s.Append(i...) |
|
| 350 |
- |
|
| 351 |
- return nil |
|
| 352 |
-} |
| ... | ... |
@@ -589,9 +589,6 @@ github.com/cyphar/filepath-securejoin/pathrs-lite/procfs |
| 589 | 589 |
# github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc |
| 590 | 590 |
## explicit |
| 591 | 591 |
github.com/davecgh/go-spew/spew |
| 592 |
-# github.com/deckarep/golang-set/v2 v2.8.0 |
|
| 593 |
-## explicit; go 1.18 |
|
| 594 |
-github.com/deckarep/golang-set/v2 |
|
| 595 | 592 |
# github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 |
| 596 | 593 |
## explicit; go 1.13 |
| 597 | 594 |
github.com/digitorus/pkcs7 |