github.com/anchore/syft@v1.38.2/syft/format/purls/encoder.go (about) 1 package purls 2 3 import ( 4 "io" 5 "strings" 6 7 "github.com/scylladb/go-set/strset" 8 9 "github.com/anchore/packageurl-go" 10 "github.com/anchore/syft/internal/log" 11 "github.com/anchore/syft/syft/sbom" 12 ) 13 14 const ID sbom.FormatID = "purls" 15 const version = "1" 16 17 type encoder struct { 18 } 19 20 func NewFormatEncoder() sbom.FormatEncoder { 21 return encoder{} 22 } 23 24 func (e encoder) ID() sbom.FormatID { 25 return ID 26 } 27 28 func (e encoder) Aliases() []string { 29 return []string{ 30 "purl", 31 } 32 } 33 34 func (e encoder) Version() string { 35 return sbom.AnyVersion 36 } 37 38 func (e encoder) Encode(writer io.Writer, s sbom.SBOM) error { 39 output := strset.New() 40 for _, p := range s.Artifacts.Packages.Sorted() { 41 purl := strings.TrimSpace(p.PURL) 42 if purl == "" || output.Has(purl) { 43 continue 44 } 45 // ensure syft doesn't output invalid PURLs in this format 46 _, err := packageurl.FromString(purl) 47 if err != nil { 48 log.Debugf("invalid purl: %q", purl) 49 continue 50 } 51 output.Add(purl) 52 _, err = writer.Write([]byte(purl)) 53 if err != nil { 54 return err 55 } 56 _, err = writer.Write([]byte("\n")) 57 if err != nil { 58 return err 59 } 60 } 61 return nil 62 }