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  }