github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/genutil/mapz/set.go (about) 1 package mapz 2 3 import ( 4 "maps" 5 6 "github.com/rs/zerolog" 7 8 expmaps "golang.org/x/exp/maps" 9 ) 10 11 // Set implements a very basic generic set. 12 type Set[T comparable] struct { 13 values map[T]struct{} 14 } 15 16 // NewSet returns a new set. 17 func NewSet[T comparable](items ...T) *Set[T] { 18 s := &Set[T]{ 19 values: map[T]struct{}{}, 20 } 21 for _, item := range items { 22 s.values[item] = struct{}{} 23 } 24 return s 25 } 26 27 // Has returns true if the set contains the given value. 28 func (s *Set[T]) Has(value T) bool { 29 _, exists := s.values[value] 30 return exists 31 } 32 33 // Add adds the given value to the set and returns true. If 34 // the value is already present, returns false. 35 func (s *Set[T]) Add(value T) bool { 36 if s.Has(value) { 37 return false 38 } 39 40 s.values[value] = struct{}{} 41 return true 42 } 43 44 // Insert adds the given value to the set. 45 func (s *Set[T]) Insert(value T) { 46 s.values[value] = struct{}{} 47 } 48 49 // Delete removes the value from the set, returning nothing. 50 func (s *Set[T]) Delete(value T) { 51 delete(s.values, value) 52 } 53 54 // Extend adds all the values to the set. 55 func (s *Set[T]) Extend(values []T) { 56 for _, value := range values { 57 s.values[value] = struct{}{} 58 } 59 } 60 61 // Merge adds all the values from the other set to this set. 62 func (s *Set[T]) Merge(other *Set[T]) { 63 for value := range other.values { 64 s.values[value] = struct{}{} 65 } 66 } 67 68 // Union adds all the values from the other set to this set, 69 // returning a new set. 70 func (s *Set[T]) Union(other *Set[T]) *Set[T] { 71 cpy := s.Copy() 72 for value := range other.values { 73 cpy.values[value] = struct{}{} 74 } 75 return cpy 76 } 77 78 // IntersectionDifference removes any values from this set that 79 // are not shared with the other set. Returns the same set. 80 func (s *Set[T]) IntersectionDifference(other *Set[T]) *Set[T] { 81 for value := range s.values { 82 if !other.Has(value) { 83 delete(s.values, value) 84 } 85 } 86 return s 87 } 88 89 // RemoveAll removes all values from this set found in the other set. 90 func (s *Set[T]) RemoveAll(other *Set[T]) { 91 for value := range other.values { 92 delete(s.values, value) 93 } 94 } 95 96 // Subtract subtracts the other set from this set, returning a new set. 97 func (s *Set[T]) Subtract(other *Set[T]) *Set[T] { 98 cpy := s.Copy() 99 cpy.RemoveAll(other) 100 return cpy 101 } 102 103 // Copy returns a copy of this set. 104 func (s *Set[T]) Copy() *Set[T] { 105 return &Set[T]{ 106 values: maps.Clone(s.values), 107 } 108 } 109 110 // Intersect removes any values from this set that 111 // are not shared with the other set, returning a new set. 112 func (s *Set[T]) Intersect(other *Set[T]) *Set[T] { 113 cpy := s.Copy() 114 for value := range cpy.values { 115 if !other.Has(value) { 116 delete(cpy.values, value) 117 } 118 } 119 return cpy 120 } 121 122 // Equal returns true if both sets have the same elements 123 func (s *Set[T]) Equal(other *Set[T]) bool { 124 return maps.Equal(s.values, other.values) 125 } 126 127 // IsEmpty returns true if the set is empty. 128 func (s *Set[T]) IsEmpty() bool { 129 return len(s.values) == 0 130 } 131 132 // AsSlice returns the set as a slice of values. 133 func (s *Set[T]) AsSlice() []T { 134 if len(s.values) == 0 { 135 return nil 136 } 137 138 return expmaps.Keys(s.values) 139 } 140 141 // Len returns the length of the set. 142 func (s *Set[T]) Len() int { 143 return len(s.values) 144 } 145 146 // ForEach executes the callback for each item in the set until an error is encountered. 147 func (s *Set[T]) ForEach(callback func(value T) error) error { 148 for value := range s.values { 149 if err := callback(value); err != nil { 150 return err 151 } 152 } 153 154 return nil 155 } 156 157 func (s *Set[T]) MarshalZerologObject(e *zerolog.Event) { 158 xs := zerolog.Arr() 159 for _, value := range s.values { 160 xs.Interface(value) 161 } 162 e.Array("values", xs) 163 }