github.com/anchore/syft@v1.38.2/syft/file/coordinate_set.go (about) 1 package file 2 3 import ( 4 "sort" 5 6 "github.com/gohugoio/hashstructure" 7 "github.com/scylladb/go-set/strset" 8 ) 9 10 // CoordinateSet provides a unique collection of Coordinates with set operations. 11 type CoordinateSet struct { 12 set map[Coordinates]struct{} 13 } 14 15 func NewCoordinateSet(coordinates ...Coordinates) (s CoordinateSet) { 16 for _, l := range coordinates { 17 s.Add(l) 18 } 19 20 return s 21 } 22 23 func (s *CoordinateSet) Add(coordinates ...Coordinates) { 24 if s.set == nil { 25 s.set = make(map[Coordinates]struct{}) 26 } 27 for _, l := range coordinates { 28 s.set[l] = struct{}{} 29 } 30 } 31 32 func (s CoordinateSet) Remove(coordinates ...Coordinates) { 33 if s.set == nil { 34 return 35 } 36 for _, l := range coordinates { 37 delete(s.set, l) 38 } 39 } 40 41 func (s CoordinateSet) Contains(l Coordinates) bool { 42 if s.set == nil { 43 return false 44 } 45 _, ok := s.set[l] 46 return ok 47 } 48 49 func (s CoordinateSet) Paths() []string { 50 if s.set == nil { 51 return nil 52 } 53 54 paths := strset.New() 55 for _, c := range s.ToSlice() { 56 paths.Add(c.RealPath) 57 } 58 pathSlice := paths.List() 59 sort.Strings(pathSlice) 60 return pathSlice 61 } 62 63 func (s CoordinateSet) ToSlice(sorters ...func(a, b Coordinates) int) []Coordinates { 64 coordinates := s.ToUnorderedSlice() 65 66 var sorted bool 67 for _, sorter := range sorters { 68 if sorter == nil { 69 continue 70 } 71 sort.Slice(coordinates, func(i, j int) bool { 72 return sorter(coordinates[i], coordinates[j]) < 0 73 }) 74 sorted = true 75 break 76 } 77 78 if !sorted { 79 sort.SliceStable(coordinates, func(i, j int) bool { 80 if coordinates[i].FileSystemID == coordinates[j].FileSystemID { 81 return coordinates[i].RealPath < coordinates[j].RealPath 82 } 83 return coordinates[i].FileSystemID < coordinates[j].FileSystemID 84 }) 85 } 86 87 return coordinates 88 } 89 90 func (s CoordinateSet) ToUnorderedSlice() []Coordinates { 91 if s.set == nil { 92 return nil 93 } 94 coordinates := make([]Coordinates, len(s.set)) 95 idx := 0 96 for v := range s.set { 97 coordinates[idx] = v 98 idx++ 99 } 100 return coordinates 101 } 102 103 func (s CoordinateSet) Hash() (uint64, error) { 104 return hashstructure.Hash(s.ToSlice(), &hashstructure.HashOptions{ 105 ZeroNil: true, 106 SlicesAsSets: true, 107 }) 108 }