experiment with encoder/decoder for data encapsulation

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Alex Goodman 2021-11-22 16:11:52 -05:00
parent f699a6add8
commit 5fb0235cfb
No known key found for this signature in database
GPG Key ID: 5CB45AE22BAB7EA7
10 changed files with 67 additions and 39 deletions

View File

@ -15,7 +15,7 @@ import (
// TODO: eventually this is the source of truth for all formatters // TODO: eventually this is the source of truth for all formatters
func All() []format.Format { func All() []format.Format {
return []format.Format{ return []format.Format{
syftjson.Format(), syftjson.Format( /*...now there is a requirement for app config here...*/ ),
table.Format(), table.Format(),
cyclonedx12xml.Format(), cyclonedx12xml.Format(),
spdx22json.Format(), spdx22json.Format(),

View File

@ -10,7 +10,10 @@ import (
"github.com/anchore/syft/internal/formats/syftjson/model" "github.com/anchore/syft/internal/formats/syftjson/model"
) )
func decoder(reader io.Reader) (*sbom.SBOM, error) { type decoder struct {
}
func (d decoder) Decode(reader io.Reader) (*sbom.SBOM, error) {
dec := json.NewDecoder(reader) dec := json.NewDecoder(reader)
var doc model.Document var doc model.Document

View File

@ -7,8 +7,12 @@ import (
"github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/sbom"
) )
func encoder(output io.Writer, s sbom.SBOM, appConfig interface{}) error { type encoder struct {
doc := ToFormatModel(s, appConfig) appConfig interface{}
}
func (e encoder) Encode(output io.Writer, s sbom.SBOM) error {
doc := ToFormatModel(s, e.appConfig)
enc := json.NewEncoder(output) enc := json.NewEncoder(output)
// prevent > and < from being escaped in the payload // prevent > and < from being escaped in the payload

View File

@ -2,11 +2,25 @@ package syftjson
import "github.com/anchore/syft/syft/format" import "github.com/anchore/syft/syft/format"
func Format() format.Format { func Format(appConfig interface{}) format.Format {
return format.NewFormat( return format.NewFormat(
format.JSONOption, format.JSONOption,
encoder, Encoder(appConfig),
decoder, Decoder(),
validator, Validator(),
) )
} }
func Encoder(appConfig interface{}) format.Encoder {
return &encoder{
appConfig: appConfig,
}
}
func Decoder() format.Decoder {
return &decoder{}
}
func Validator() format.Validator {
return &validator{}
}

View File

@ -9,7 +9,10 @@ import (
"github.com/anchore/syft/internal/formats/syftjson/model" "github.com/anchore/syft/internal/formats/syftjson/model"
) )
func validator(reader io.Reader) error { type validator struct {
}
func (v validator) Validate(reader io.Reader) error {
type Document struct { type Document struct {
Schema model.Schema `json:"schema"` Schema model.Schema `json:"schema"`
} }

View File

@ -6,5 +6,7 @@ import (
"github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/sbom"
) )
// Decoder is a function that can convert an SBOM document of a specific format from a reader into Syft native objects. // Decoder is an object that can convert an SBOM document of a specific format from a reader into Syft native objects.
type Decoder func(reader io.Reader) (*sbom.SBOM, error) type Decoder interface {
Decode(reader io.Reader) (*sbom.SBOM, error)
}

View File

@ -6,5 +6,7 @@ import (
"github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/sbom"
) )
// Encoder is a function that can transform Syft native objects into an SBOM document of a specific format written to the given writer. // Encoder is a function that can transform Syft native objects from an SBOM document of a specific format written to the given writer.
type Encoder func(io.Writer, sbom.SBOM, interface{}) error type Encoder interface {
Encode(io.Writer, sbom.SBOM) error
}

View File

@ -15,45 +15,45 @@ var (
type Format struct { type Format struct {
Option Option Option Option
encoder Encoder Encoder
decoder Decoder Decoder
validator Validator Validator
} }
func NewFormat(option Option, encoder Encoder, decoder Decoder, validator Validator) Format { func NewFormat(option Option, encoder Encoder, decoder Decoder, validator Validator) Format {
return Format{ return Format{
Option: option, Option: option,
encoder: encoder, Encoder: encoder,
decoder: decoder, Decoder: decoder,
validator: validator, Validator: validator,
} }
} }
func (f Format) Encode(output io.Writer, s sbom.SBOM, appConfig interface{}) error { func (f Format) Encode(output io.Writer, s sbom.SBOM) error {
if f.encoder == nil { if f.Encoder == nil {
return ErrEncodingNotSupported return ErrEncodingNotSupported
} }
return f.encoder(output, s, appConfig) return f.Encoder.Encode(output, s)
} }
func (f Format) Decode(reader io.Reader) (*sbom.SBOM, error) { func (f Format) Decode(reader io.Reader) (*sbom.SBOM, error) {
if f.decoder == nil { if f.Decoder == nil {
return nil, ErrDecodingNotSupported return nil, ErrDecodingNotSupported
} }
return f.decoder(reader) return f.Decoder.Decode(reader)
} }
func (f Format) Validate(reader io.Reader) error { func (f Format) Validate(reader io.Reader) error {
if f.validator == nil { if f.Validator == nil {
return ErrValidationNotSupported return ErrValidationNotSupported
} }
return f.validator(reader) return f.Validator.Validate(reader)
} }
func (f Format) Presenter(s sbom.SBOM, appConfig interface{}) *Presenter { func (f Format) Presenter(s sbom.SBOM) *Presenter {
if f.encoder == nil { if f.Encoder == nil {
return nil return nil
} }
return NewPresenter(f.encoder, s, appConfig) return NewPresenter(f.Encoder, s)
} }

View File

@ -8,18 +8,16 @@ import (
type Presenter struct { type Presenter struct {
sbom sbom.SBOM sbom sbom.SBOM
appConfig interface{}
encoder Encoder encoder Encoder
} }
func NewPresenter(encoder Encoder, s sbom.SBOM, appConfig interface{}) *Presenter { func NewPresenter(encoder Encoder, s sbom.SBOM) *Presenter {
return &Presenter{ return &Presenter{
sbom: s, sbom: s,
appConfig: appConfig,
encoder: encoder, encoder: encoder,
} }
} }
func (pres *Presenter) Present(output io.Writer) error { func (pres *Presenter) Present(output io.Writer) error {
return pres.encoder(output, pres.sbom, pres.appConfig) return pres.encoder.Encode(output, pres.sbom)
} }

View File

@ -9,4 +9,6 @@ import "io"
// assertions protect against "simple" format decoding validations that may lead to false positives (e.g. I decoded // assertions protect against "simple" format decoding validations that may lead to false positives (e.g. I decoded
// json successfully therefore this must be the target format, however, all values are their default zero-value and // json successfully therefore this must be the target format, however, all values are their default zero-value and
// really represent a different format that also uses json) // really represent a different format that also uses json)
type Validator func(reader io.Reader) error type Validator interface {
Validate(reader io.Reader) error
}