github.com/moby/docker@v26.1.3+incompatible/libnetwork/internal/setmatrix/setmatrix.go (about) 1 // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: 2 //go:build go1.19 3 4 package setmatrix 5 6 import ( 7 "sync" 8 9 mapset "github.com/deckarep/golang-set/v2" 10 ) 11 12 // SetMatrix is a map of Sets. 13 // The zero value is an empty set matrix ready to use. 14 // 15 // SetMatrix values are safe for concurrent use. 16 type SetMatrix[T comparable] struct { 17 matrix map[string]mapset.Set[T] 18 19 mu sync.Mutex 20 } 21 22 // Get returns the members of the set for a specific key as a slice. 23 func (s *SetMatrix[T]) Get(key string) ([]T, bool) { 24 s.mu.Lock() 25 defer s.mu.Unlock() 26 set, ok := s.matrix[key] 27 if !ok { 28 return nil, ok 29 } 30 return set.ToSlice(), ok 31 } 32 33 // Contains is used to verify if an element is in a set for a specific key. 34 func (s *SetMatrix[T]) Contains(key string, value T) (containsElement, setExists bool) { 35 s.mu.Lock() 36 defer s.mu.Unlock() 37 set, ok := s.matrix[key] 38 if !ok { 39 return false, ok 40 } 41 return set.Contains(value), ok 42 } 43 44 // Insert inserts the value in the set of a key and returns whether the value is 45 // inserted (was not already in the set) and the number of elements in the set. 46 func (s *SetMatrix[T]) Insert(key string, value T) (inserted bool, cardinality int) { 47 s.mu.Lock() 48 defer s.mu.Unlock() 49 set, ok := s.matrix[key] 50 if !ok { 51 if s.matrix == nil { 52 s.matrix = make(map[string]mapset.Set[T]) 53 } 54 s.matrix[key] = mapset.NewThreadUnsafeSet(value) 55 return true, 1 56 } 57 58 return set.Add(value), set.Cardinality() 59 } 60 61 // Remove removes the value in the set for a specific key. 62 func (s *SetMatrix[T]) Remove(key string, value T) (removed bool, cardinality int) { 63 s.mu.Lock() 64 defer s.mu.Unlock() 65 set, ok := s.matrix[key] 66 if !ok { 67 return false, 0 68 } 69 70 if set.Contains(value) { 71 set.Remove(value) 72 removed = true 73 // If the set is empty remove it from the matrix 74 if set.Cardinality() == 0 { 75 delete(s.matrix, key) 76 } 77 } 78 79 return removed, set.Cardinality() 80 } 81 82 // Cardinality returns the number of elements in the set for a key. 83 func (s *SetMatrix[T]) Cardinality(key string) (cardinality int, ok bool) { 84 s.mu.Lock() 85 defer s.mu.Unlock() 86 set, ok := s.matrix[key] 87 if !ok { 88 return 0, ok 89 } 90 91 return set.Cardinality(), ok 92 } 93 94 // String returns the string version of the set. 95 // The empty string is returned if there is no set for key. 96 func (s *SetMatrix[T]) String(key string) (v string, ok bool) { 97 s.mu.Lock() 98 defer s.mu.Unlock() 99 set, ok := s.matrix[key] 100 if !ok { 101 return "", ok 102 } 103 return set.String(), ok 104 } 105 106 // Keys returns all the keys in the map. 107 func (s *SetMatrix[T]) Keys() []string { 108 s.mu.Lock() 109 defer s.mu.Unlock() 110 keys := make([]string, 0, len(s.matrix)) 111 for k := range s.matrix { 112 keys = append(keys, k) 113 } 114 return keys 115 }