github.com/boxboat/in-toto-golang@v0.0.3-0.20210303203820-2fa16ecbe6f6/in_toto/util.go (about)

     1  package in_toto
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  )
     7  
     8  /*
     9  Set represents a data structure for set operations. See `NewSet` for how to
    10  create a Set, and available Set receivers for useful set operations.
    11  
    12  Under the hood Set aliases map[string]struct{}, where the map keys are the set
    13  elements and the map values are a memory-efficient way of storing the keys.
    14  */
    15  type Set map[string]struct{}
    16  
    17  /*
    18  NewSet creates a new Set, assigns it the optionally passed variadic string
    19  elements, and returns it.
    20  */
    21  func NewSet(elems ...string) Set {
    22  	var s Set
    23  	s = make(map[string]struct{})
    24  	for _, elem := range elems {
    25  		s.Add(elem)
    26  	}
    27  	return s
    28  }
    29  
    30  /*
    31  Has returns True if the passed string is member of the set on which it was
    32  called and False otherwise.
    33  */
    34  func (s Set) Has(elem string) bool {
    35  	_, ok := s[elem]
    36  	return ok
    37  }
    38  
    39  /*
    40  Add adds the passed string to the set on which it was called, if the string is
    41  not a member of the set.
    42  */
    43  func (s Set) Add(elem string) {
    44  	s[elem] = struct{}{}
    45  }
    46  
    47  /*
    48  Remove removes the passed string from the set on which was is called, if the
    49  string is a member of the set.
    50  */
    51  func (s Set) Remove(elem string) {
    52  	delete(s, elem)
    53  }
    54  
    55  /*
    56  Intersection creates and returns a new Set with the elements of the set on
    57  which it was called that are also in the passed set.
    58  */
    59  func (s Set) Intersection(s2 Set) Set {
    60  	res := NewSet()
    61  	for elem := range s {
    62  		if s2.Has(elem) == false {
    63  			continue
    64  		}
    65  		res.Add(elem)
    66  	}
    67  	return res
    68  }
    69  
    70  /*
    71  Difference creates and returns a new Set with the elements of the set on
    72  which it was called that are not in the passed set.
    73  */
    74  func (s Set) Difference(s2 Set) Set {
    75  	res := NewSet()
    76  	for elem := range s {
    77  		if s2.Has(elem) {
    78  			continue
    79  		}
    80  		res.Add(elem)
    81  	}
    82  	return res
    83  }
    84  
    85  /*
    86  Filter creates and returns a new Set with the elements of the set on which it
    87  was called that match the passed pattern. A matching error is treated like a
    88  non-match plus a warning is printed.
    89  */
    90  func (s Set) Filter(pattern string) Set {
    91  	res := NewSet()
    92  	for elem := range s {
    93  		matched, err := filepath.Match(pattern, elem)
    94  		if err != nil {
    95  			fmt.Printf("WARNING: %s, pattern was '%s'\n", err, pattern)
    96  			continue
    97  		}
    98  		if !matched {
    99  			continue
   100  		}
   101  		res.Add(elem)
   102  	}
   103  	return res
   104  }
   105  
   106  /*
   107  Slice creates and returns an unordered string slice with the elements of the
   108  set on which it was called.
   109  */
   110  func (s Set) Slice() []string {
   111  	var res []string
   112  	res = make([]string, 0, len(s))
   113  	for elem := range s {
   114  		res = append(res, elem)
   115  	}
   116  	return res
   117  }
   118  
   119  /*
   120  InterfaceKeyStrings returns string keys of passed interface{} map in an
   121  unordered string slice.
   122  */
   123  func InterfaceKeyStrings(m map[string]interface{}) []string {
   124  	res := make([]string, len(m))
   125  	i := 0
   126  	for k := range m {
   127  		res[i] = k
   128  		i++
   129  	}
   130  	return res
   131  }
   132  
   133  /*
   134  IsSubSet checks if the parameter subset is a
   135  subset of the superset s.
   136  */
   137  func (s Set) IsSubSet(subset Set) bool {
   138  	if len(subset) > len(s) {
   139  		return false
   140  	}
   141  	for key := range subset {
   142  		if s.Has(key) {
   143  			continue
   144  		} else {
   145  			return false
   146  		}
   147  	}
   148  	return true
   149  }