package artifacts import ( "bytes" "encoding/json" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/partial" "github.com/google/go-containerregistry/pkg/v1/types" "hauler.dev/go/hauler/pkg/consts" ) var _ partial.Describable = (*marshallableConfig)(nil) type Config interface { // Raw returns the config bytes Raw() ([]byte, error) Digest() (v1.Hash, error) MediaType() (types.MediaType, error) Size() (int64, error) } type Marshallable interface{} type ConfigOption func(*marshallableConfig) // ToConfig takes anything that is marshallabe and converts it into a Config func ToConfig(i Marshallable, opts ...ConfigOption) Config { mc := &marshallableConfig{Marshallable: i} for _, o := range opts { o(mc) } return mc } func WithConfigMediaType(mediaType string) ConfigOption { return func(config *marshallableConfig) { config.mediaType = mediaType } } // marshallableConfig implements Config using helper methods type marshallableConfig struct { Marshallable mediaType string } func (c *marshallableConfig) MediaType() (types.MediaType, error) { mt := c.mediaType if mt == "" { mt = consts.UnknownManifest } return types.MediaType(mt), nil } func (c *marshallableConfig) Raw() ([]byte, error) { return json.Marshal(c.Marshallable) } func (c *marshallableConfig) Digest() (v1.Hash, error) { return Digest(c) } func (c *marshallableConfig) Size() (int64, error) { return Size(c) } type WithRawConfig interface { Raw() ([]byte, error) } func Digest(c WithRawConfig) (v1.Hash, error) { b, err := c.Raw() if err != nil { return v1.Hash{}, err } digest, _, err := v1.SHA256(bytes.NewReader(b)) return digest, err } func Size(c WithRawConfig) (int64, error) { b, err := c.Raw() if err != nil { return -1, err } return int64(len(b)), nil }