From 5fb0235cfb71fd968af948a3d21b63ed9d972fd1 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 22 Nov 2021 16:11:52 -0500 Subject: [PATCH] experiment with encoder/decoder for data encapsulation Signed-off-by: Alex Goodman --- internal/formats/formats.go | 2 +- internal/formats/syftjson/decoder.go | 5 +++- internal/formats/syftjson/encoder.go | 8 ++++-- internal/formats/syftjson/format.go | 22 ++++++++++++++--- internal/formats/syftjson/validator.go | 5 +++- syft/format/decoder.go | 6 +++-- syft/format/encoder.go | 6 +++-- syft/format/format.go | 34 +++++++++++++------------- syft/format/presenter.go | 14 +++++------ syft/format/validator.go | 4 ++- 10 files changed, 67 insertions(+), 39 deletions(-) diff --git a/internal/formats/formats.go b/internal/formats/formats.go index aa5dcc649..c5eecfc42 100644 --- a/internal/formats/formats.go +++ b/internal/formats/formats.go @@ -15,7 +15,7 @@ import ( // TODO: eventually this is the source of truth for all formatters func All() []format.Format { return []format.Format{ - syftjson.Format(), + syftjson.Format( /*...now there is a requirement for app config here...*/ ), table.Format(), cyclonedx12xml.Format(), spdx22json.Format(), diff --git a/internal/formats/syftjson/decoder.go b/internal/formats/syftjson/decoder.go index 95f16fdd2..8d9154b48 100644 --- a/internal/formats/syftjson/decoder.go +++ b/internal/formats/syftjson/decoder.go @@ -10,7 +10,10 @@ import ( "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) var doc model.Document diff --git a/internal/formats/syftjson/encoder.go b/internal/formats/syftjson/encoder.go index b358554ac..28c1ef44d 100644 --- a/internal/formats/syftjson/encoder.go +++ b/internal/formats/syftjson/encoder.go @@ -7,8 +7,12 @@ import ( "github.com/anchore/syft/syft/sbom" ) -func encoder(output io.Writer, s sbom.SBOM, appConfig interface{}) error { - doc := ToFormatModel(s, appConfig) +type encoder struct { + appConfig interface{} +} + +func (e encoder) Encode(output io.Writer, s sbom.SBOM) error { + doc := ToFormatModel(s, e.appConfig) enc := json.NewEncoder(output) // prevent > and < from being escaped in the payload diff --git a/internal/formats/syftjson/format.go b/internal/formats/syftjson/format.go index bc3f51642..013b7de7a 100644 --- a/internal/formats/syftjson/format.go +++ b/internal/formats/syftjson/format.go @@ -2,11 +2,25 @@ package syftjson import "github.com/anchore/syft/syft/format" -func Format() format.Format { +func Format(appConfig interface{}) format.Format { return format.NewFormat( format.JSONOption, - encoder, - decoder, - validator, + Encoder(appConfig), + Decoder(), + Validator(), ) } + +func Encoder(appConfig interface{}) format.Encoder { + return &encoder{ + appConfig: appConfig, + } +} + +func Decoder() format.Decoder { + return &decoder{} +} + +func Validator() format.Validator { + return &validator{} +} diff --git a/internal/formats/syftjson/validator.go b/internal/formats/syftjson/validator.go index d359b60d9..968dc9a24 100644 --- a/internal/formats/syftjson/validator.go +++ b/internal/formats/syftjson/validator.go @@ -9,7 +9,10 @@ import ( "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 { Schema model.Schema `json:"schema"` } diff --git a/syft/format/decoder.go b/syft/format/decoder.go index bdeb0afbf..b419e4c00 100644 --- a/syft/format/decoder.go +++ b/syft/format/decoder.go @@ -6,5 +6,7 @@ import ( "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. -type Decoder func(reader io.Reader) (*sbom.SBOM, error) +// Decoder is an object that can convert an SBOM document of a specific format from a reader into Syft native objects. +type Decoder interface { + Decode(reader io.Reader) (*sbom.SBOM, error) +} diff --git a/syft/format/encoder.go b/syft/format/encoder.go index 3c5ed3c26..10e7e124f 100644 --- a/syft/format/encoder.go +++ b/syft/format/encoder.go @@ -6,5 +6,7 @@ import ( "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. -type Encoder func(io.Writer, sbom.SBOM, interface{}) error +// 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 interface { + Encode(io.Writer, sbom.SBOM) error +} diff --git a/syft/format/format.go b/syft/format/format.go index 65bf18288..f09c030a2 100644 --- a/syft/format/format.go +++ b/syft/format/format.go @@ -14,46 +14,46 @@ var ( ) type Format struct { - Option Option - encoder Encoder - decoder Decoder - validator Validator + Option Option + Encoder + Decoder + Validator } func NewFormat(option Option, encoder Encoder, decoder Decoder, validator Validator) Format { return Format{ Option: option, - encoder: encoder, - decoder: decoder, - validator: validator, + Encoder: encoder, + Decoder: decoder, + Validator: validator, } } -func (f Format) Encode(output io.Writer, s sbom.SBOM, appConfig interface{}) error { - if f.encoder == nil { +func (f Format) Encode(output io.Writer, s sbom.SBOM) error { + if f.Encoder == nil { return ErrEncodingNotSupported } - return f.encoder(output, s, appConfig) + return f.Encoder.Encode(output, s) } func (f Format) Decode(reader io.Reader) (*sbom.SBOM, error) { - if f.decoder == nil { + if f.Decoder == nil { return nil, ErrDecodingNotSupported } - return f.decoder(reader) + return f.Decoder.Decode(reader) } func (f Format) Validate(reader io.Reader) error { - if f.validator == nil { + if f.Validator == nil { return ErrValidationNotSupported } - return f.validator(reader) + return f.Validator.Validate(reader) } -func (f Format) Presenter(s sbom.SBOM, appConfig interface{}) *Presenter { - if f.encoder == nil { +func (f Format) Presenter(s sbom.SBOM) *Presenter { + if f.Encoder == nil { return nil } - return NewPresenter(f.encoder, s, appConfig) + return NewPresenter(f.Encoder, s) } diff --git a/syft/format/presenter.go b/syft/format/presenter.go index fc920c8d8..c85b564b8 100644 --- a/syft/format/presenter.go +++ b/syft/format/presenter.go @@ -7,19 +7,17 @@ import ( ) type Presenter struct { - sbom sbom.SBOM - appConfig interface{} - encoder Encoder + sbom sbom.SBOM + encoder Encoder } -func NewPresenter(encoder Encoder, s sbom.SBOM, appConfig interface{}) *Presenter { +func NewPresenter(encoder Encoder, s sbom.SBOM) *Presenter { return &Presenter{ - sbom: s, - appConfig: appConfig, - encoder: encoder, + sbom: s, + encoder: encoder, } } func (pres *Presenter) Present(output io.Writer) error { - return pres.encoder(output, pres.sbom, pres.appConfig) + return pres.encoder.Encode(output, pres.sbom) } diff --git a/syft/format/validator.go b/syft/format/validator.go index 6559186b0..74a0963e2 100644 --- a/syft/format/validator.go +++ b/syft/format/validator.go @@ -9,4 +9,6 @@ import "io" // 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 // really represent a different format that also uses json) -type Validator func(reader io.Reader) error +type Validator interface { + Validate(reader io.Reader) error +}