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
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(),

View File

@ -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

View File

@ -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

View File

@ -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{}
}

View File

@ -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"`
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}

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
// 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
}