github.com/kastenhq/syft@v0.0.0-20230821225854-0710af25cdbe/syft/file/coordinate_set.go (about) 1 package file 2 3 import ( 4 "sort" 5 6 "github.com/mitchellh/hashstructure/v2" 7 "github.com/scylladb/go-set/strset" 8 ) 9 10 type CoordinateSet struct { 11 set map[Coordinates]struct{} 12 } 13 14 func NewCoordinateSet(coordinates ...Coordinates) (s CoordinateSet) { 15 for _, l := range coordinates { 16 s.Add(l) 17 } 18 19 return s 20 } 21 22 func (s *CoordinateSet) Add(coordinates ...Coordinates) { 23 if s.set == nil { 24 s.set = make(map[Coordinates]struct{}) 25 } 26 for _, l := range coordinates { 27 s.set[l] = struct{}{} 28 } 29 } 30 31 func (s CoordinateSet) Remove(coordinates ...Coordinates) { 32 if s.set == nil { 33 return 34 } 35 for _, l := range coordinates { 36 delete(s.set, l) 37 } 38 } 39 40 func (s CoordinateSet) Contains(l Coordinates) bool { 41 if s.set == nil { 42 return false 43 } 44 _, ok := s.set[l] 45 return ok 46 } 47 48 func (s CoordinateSet) Paths() []string { 49 if s.set == nil { 50 return nil 51 } 52 53 paths := strset.New() 54 for _, c := range s.ToSlice() { 55 paths.Add(c.RealPath) 56 } 57 pathSlice := paths.List() 58 sort.Strings(pathSlice) 59 return pathSlice 60 } 61 62 func (s CoordinateSet) ToSlice() []Coordinates { 63 if s.set == nil { 64 return nil 65 } 66 coordinates := make([]Coordinates, len(s.set)) 67 idx := 0 68 for v := range s.set { 69 coordinates[idx] = v 70 idx++ 71 } 72 sort.SliceStable(coordinates, func(i, j int) bool { 73 if coordinates[i].RealPath == coordinates[j].RealPath { 74 return coordinates[i].FileSystemID < coordinates[j].FileSystemID 75 } 76 return coordinates[i].RealPath < coordinates[j].RealPath 77 }) 78 return coordinates 79 } 80 81 func (s CoordinateSet) Hash() (uint64, error) { 82 return hashstructure.Hash(s.ToSlice(), hashstructure.FormatV2, &hashstructure.HashOptions{ 83 ZeroNil: true, 84 SlicesAsSets: true, 85 }) 86 }