github.com/in-toto/in-toto-golang@v0.9.1-0.20240517212500-990269f763cf/in_toto/util.go (about) 1 package in_toto 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "reflect" 8 "strings" 9 ) 10 11 var ErrUnknownMetadataType = errors.New("unknown metadata type encountered: not link or layout") 12 13 /* 14 Set represents a data structure for set operations. See `NewSet` for how to 15 create a Set, and available Set receivers for useful set operations. 16 17 Under the hood Set aliases map[string]struct{}, where the map keys are the set 18 elements and the map values are a memory-efficient way of storing the keys. 19 */ 20 type Set map[string]struct{} 21 22 /* 23 NewSet creates a new Set, assigns it the optionally passed variadic string 24 elements, and returns it. 25 */ 26 func NewSet(elems ...string) Set { 27 var s Set = make(map[string]struct{}) 28 for _, elem := range elems { 29 s.Add(elem) 30 } 31 return s 32 } 33 34 /* 35 Has returns True if the passed string is member of the set on which it was 36 called and False otherwise. 37 */ 38 func (s Set) Has(elem string) bool { 39 _, ok := s[elem] 40 return ok 41 } 42 43 /* 44 Add adds the passed string to the set on which it was called, if the string is 45 not a member of the set. 46 */ 47 func (s Set) Add(elem string) { 48 s[elem] = struct{}{} 49 } 50 51 /* 52 Remove removes the passed string from the set on which was is called, if the 53 string is a member of the set. 54 */ 55 func (s Set) Remove(elem string) { 56 delete(s, elem) 57 } 58 59 /* 60 Intersection creates and returns a new Set with the elements of the set on 61 which it was called that are also in the passed set. 62 */ 63 func (s Set) Intersection(s2 Set) Set { 64 res := NewSet() 65 for elem := range s { 66 if !s2.Has(elem) { 67 continue 68 } 69 res.Add(elem) 70 } 71 return res 72 } 73 74 /* 75 Difference creates and returns a new Set with the elements of the set on 76 which it was called that are not in the passed set. 77 */ 78 func (s Set) Difference(s2 Set) Set { 79 res := NewSet() 80 for elem := range s { 81 if s2.Has(elem) { 82 continue 83 } 84 res.Add(elem) 85 } 86 return res 87 } 88 89 /* 90 Filter creates and returns a new Set with the elements of the set on which it 91 was called that match the passed pattern. A matching error is treated like a 92 non-match plus a warning is printed. 93 */ 94 func (s Set) Filter(pattern string) Set { 95 res := NewSet() 96 for elem := range s { 97 matched, err := match(pattern, elem) 98 if err != nil { 99 fmt.Printf("WARNING: %s, pattern was '%s'\n", err, pattern) 100 continue 101 } 102 if !matched { 103 continue 104 } 105 res.Add(elem) 106 } 107 return res 108 } 109 110 /* 111 Slice creates and returns an unordered string slice with the elements of the 112 set on which it was called. 113 */ 114 func (s Set) Slice() []string { 115 var res []string 116 res = make([]string, 0, len(s)) 117 for elem := range s { 118 res = append(res, elem) 119 } 120 return res 121 } 122 123 /* 124 artifactsDictKeyStrings returns string keys of passed HashObj map in an 125 unordered string slice. 126 */ 127 func artifactsDictKeyStrings(m map[string]HashObj) []string { 128 res := make([]string, len(m)) 129 i := 0 130 for k := range m { 131 res[i] = k 132 i++ 133 } 134 return res 135 } 136 137 /* 138 IsSubSet checks if the parameter subset is a 139 subset of the superset s. 140 */ 141 func (s Set) IsSubSet(subset Set) bool { 142 if len(subset) > len(s) { 143 return false 144 } 145 for key := range subset { 146 if s.Has(key) { 147 continue 148 } else { 149 return false 150 } 151 } 152 return true 153 } 154 155 func loadPayload(payloadBytes []byte) (any, error) { 156 var payload map[string]any 157 if err := json.Unmarshal(payloadBytes, &payload); err != nil { 158 return nil, fmt.Errorf("error decoding payload: %w", err) 159 } 160 161 if payload["_type"] == "link" { 162 var link Link 163 if err := checkRequiredJSONFields(payload, reflect.TypeOf(link)); err != nil { 164 return nil, fmt.Errorf("error decoding payload: %w", err) 165 } 166 167 decoder := json.NewDecoder(strings.NewReader(string(payloadBytes))) 168 decoder.DisallowUnknownFields() 169 if err := decoder.Decode(&link); err != nil { 170 return nil, fmt.Errorf("error decoding payload: %w", err) 171 } 172 173 return link, nil 174 } else if payload["_type"] == "layout" { 175 var layout Layout 176 if err := checkRequiredJSONFields(payload, reflect.TypeOf(layout)); err != nil { 177 return nil, fmt.Errorf("error decoding payload: %w", err) 178 } 179 180 decoder := json.NewDecoder(strings.NewReader(string(payloadBytes))) 181 decoder.DisallowUnknownFields() 182 if err := decoder.Decode(&layout); err != nil { 183 return nil, fmt.Errorf("error decoding payload: %w", err) 184 } 185 186 return layout, nil 187 } 188 189 return nil, ErrUnknownMetadataType 190 }