syft/syft/file/coordinate_set.go
Alex Goodman a77d24e379
Improve struct and field comments and incorporate into json schema (#4252)
* improve struct and field comments and incorporate into json schema

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* address review feedback

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2025-10-03 17:01:56 +00:00

109 lines
2.1 KiB
Go

package file
import (
"sort"
"github.com/gohugoio/hashstructure"
"github.com/scylladb/go-set/strset"
)
// CoordinateSet provides a unique collection of Coordinates with set operations.
type CoordinateSet struct {
set map[Coordinates]struct{}
}
func NewCoordinateSet(coordinates ...Coordinates) (s CoordinateSet) {
for _, l := range coordinates {
s.Add(l)
}
return s
}
func (s *CoordinateSet) Add(coordinates ...Coordinates) {
if s.set == nil {
s.set = make(map[Coordinates]struct{})
}
for _, l := range coordinates {
s.set[l] = struct{}{}
}
}
func (s CoordinateSet) Remove(coordinates ...Coordinates) {
if s.set == nil {
return
}
for _, l := range coordinates {
delete(s.set, l)
}
}
func (s CoordinateSet) Contains(l Coordinates) bool {
if s.set == nil {
return false
}
_, ok := s.set[l]
return ok
}
func (s CoordinateSet) Paths() []string {
if s.set == nil {
return nil
}
paths := strset.New()
for _, c := range s.ToSlice() {
paths.Add(c.RealPath)
}
pathSlice := paths.List()
sort.Strings(pathSlice)
return pathSlice
}
func (s CoordinateSet) ToSlice(sorters ...func(a, b Coordinates) int) []Coordinates {
coordinates := s.ToUnorderedSlice()
var sorted bool
for _, sorter := range sorters {
if sorter == nil {
continue
}
sort.Slice(coordinates, func(i, j int) bool {
return sorter(coordinates[i], coordinates[j]) < 0
})
sorted = true
break
}
if !sorted {
sort.SliceStable(coordinates, func(i, j int) bool {
if coordinates[i].FileSystemID == coordinates[j].FileSystemID {
return coordinates[i].RealPath < coordinates[j].RealPath
}
return coordinates[i].FileSystemID < coordinates[j].FileSystemID
})
}
return coordinates
}
func (s CoordinateSet) ToUnorderedSlice() []Coordinates {
if s.set == nil {
return nil
}
coordinates := make([]Coordinates, len(s.set))
idx := 0
for v := range s.set {
coordinates[idx] = v
idx++
}
return coordinates
}
func (s CoordinateSet) Hash() (uint64, error) {
return hashstructure.Hash(s.ToSlice(), &hashstructure.HashOptions{
ZeroNil: true,
SlicesAsSets: true,
})
}